Skip to content

Commit

Permalink
Set location issue (#147)
Browse files Browse the repository at this point in the history
* Fixed rerender issue

* Fixed reverse geocoded address

* Fixed wrong coordinates resolved from mapbox

* Propagate map pin coordinate

* Fixed device info refresh

* Fixed delegate implementation

* Temp fix for CI

---------

Co-authored-by: Pantelis Giazitsis <[email protected]>
  • Loading branch information
pantelisss and Pantelis Giazitsis authored Sep 13, 2024
1 parent ec8ff44 commit 5f71e62
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ struct SelectLocationMapView: View {
MapBoxClaimDeviceView(location: $viewModel.selectedCoordinate,
annotationTitle: Binding(get: { viewModel.selectedDeviceLocation?.name },
set: { _ in }),
geometryProxyForFrameOfMapView: proxy.frame(in: .local))
geometryProxyForFrameOfMapView: proxy.frame(in: .local),
mapControls: viewModel.mapControls)

searchArea
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,30 @@ import Combine
import DomainLayer

protocol SelectLocationMapViewModelDelegate: AnyObject {
func updatedSelectedLocation(location: DeviceLocation?)
func updatedResolvedLocation(location: DeviceLocation?)
func updatedSelectedCoordinate(coordinate: CLLocationCoordinate2D?)
}

// Make protocol functions optional
extension SelectLocationMapViewModelDelegate {
func updatedResolvedLocation(location: DeviceLocation?) {}
func updatedSelectedCoordinate(coordinate: CLLocationCoordinate2D?) {}
}

class SelectLocationMapViewModel: ObservableObject {
@Published var selectedCoordinate: CLLocationCoordinate2D
@Published var selectedCoordinate: CLLocationCoordinate2D {
didSet {
delegate?.updatedSelectedCoordinate(coordinate: selectedCoordinate)
}
}
@Published private(set) var selectedDeviceLocation: DeviceLocation? {
didSet {
delegate?.updatedSelectedLocation(location: selectedDeviceLocation)
delegate?.updatedResolvedLocation(location: selectedDeviceLocation)
}
}
@Published var searchTerm: String = ""
@Published private(set) var searchResults: [DeviceLocationSearchResult] = []
var mapControls: MapControls = .init()
private var cancellableSet: Set<AnyCancellable> = .init()
private var latestTask: Cancellable?
let useCase: DeviceLocationUseCase
Expand Down Expand Up @@ -54,17 +66,21 @@ class SelectLocationMapViewModel: ObservableObject {
func handleSearchResultTap(result: DeviceLocationSearchResult) {
latestTask?.cancel()
latestTask = useCase.locationFromSearchResult(result).sink { [weak self] location in
self?.selectedCoordinate = location.coordinates.toCLLocationCoordinate2D()
self?.mapControls.setMapCenter?(location.coordinates.toCLLocationCoordinate2D())
}
}

func moveToUserLocation() {
Task {
let result = await useCase.getUserLocation()
Task { [weak self] in
guard let self else {
return
}

let result = await self.useCase.getUserLocation()
DispatchQueue.main.async {
switch result {
case .success(let coordinates):
self.selectedCoordinate = coordinates
self.mapControls.setMapCenter?(coordinates)
case .failure(let error):
switch error {
case .locationNotFound:
Expand All @@ -85,7 +101,9 @@ class SelectLocationMapViewModel: ObservableObject {
private extension SelectLocationMapViewModel {
func getLocationFromCoordinate() {
latestTask?.cancel()
print("selectedCoordinate: \(selectedCoordinate)" )
latestTask = useCase.locationFromCoordinates(LocationCoordinates.fromCLLocationCoordinate2D(selectedCoordinate)).sink { [weak self] location in
print("selectedDeviceLocation: \(location?.coordinates)" )
self?.selectedDeviceLocation = location
}
}
Expand Down
21 changes: 13 additions & 8 deletions PresentationLayer/UIComponents/MapBox/MapBoxClaimDevice.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ struct MapBoxClaimDeviceView: View {
private let markerSize: CGSize = CGSize(width: 44.0, height: 44.0)
@State private var locationPoint: CGPoint = .zero
@State private var markerViewSize: CGSize = .zero
@StateObject private var controls: MapBoxClaimDevice.MapControls = .init()
@StateObject private var controls: MapControls

init(location: Binding<CLLocationCoordinate2D>,
annotationTitle: Binding<String?>,
geometryProxyForFrameOfMapView: CGRect) {
geometryProxyForFrameOfMapView: CGRect,
mapControls: MapControls) {
_location = location
_annotationTitle = annotationTitle
self.geometryProxyForFrameOfMapView = geometryProxyForFrameOfMapView
_controls = StateObject(wrappedValue: mapControls)
}

var body: some View {
Expand Down Expand Up @@ -103,19 +105,21 @@ private struct MapBoxClaimDevice: UIViewControllerRepresentable {
controller?.zoomOut()
}

controls.setMapCenter = { [weak controller] coordinate in
controller?.setCenter(coordinate)
}

return controller
}

func updateUIViewController(_ controller: MapViewLocationController, context _: Context) {
controller.setCenter(location)
}
}

extension MapBoxClaimDevice {
class MapControls: ObservableObject {
var zoomInAction: VoidCallback?
var zoomOutAction: VoidCallback?
}
class MapControls: ObservableObject {
var zoomInAction: VoidCallback?
var zoomOutAction: VoidCallback?
var setMapCenter: GenericCallback<CLLocationCoordinate2D>?
}

class MapViewLocationController: UIViewController {
Expand Down Expand Up @@ -182,6 +186,7 @@ class MapViewLocationController: UIViewController {
}
}.store(in: &cancelablesSet)

setCenter(location)
}

func setCenter(_ center: CLLocationCoordinate2D) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class ClaimDeviceLocationViewModel: ObservableObject {
}

extension ClaimDeviceLocationViewModel: SelectLocationMapViewModelDelegate {
func updatedSelectedLocation(location: DeviceLocation?) {
func updatedResolvedLocation(location: DeviceLocation?) {
self.selectedLocation = location
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ extension DeviceInfoRowView {
static func == (lhs: DeviceInfoRowView.Row, rhs: DeviceInfoRowView.Row) -> Bool {
lhs.title == rhs.title &&
lhs.description == rhs.description &&
lhs.imageUrl == rhs.imageUrl &&
lhs.buttonInfo == rhs.buttonInfo &&
lhs.warning == rhs.warning
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class SelectStationLocationViewModel: ObservableObject {
let deviceLocationUseCase: DeviceLocationUseCase
let meUseCase: MeUseCase
@Published var termsAccepted: Bool = false
@Published private(set) var selectedDeviceLocation: DeviceLocation?
@Published private(set) var selectedCoordinate: CLLocationCoordinate2D?
@Published var isSuccessful: Bool = false
private(set) var successObj: FailSuccessStateObject = .emptyObj
let locationViewModel: SelectLocationMapViewModel
Expand All @@ -42,7 +42,7 @@ class SelectStationLocationViewModel: ObservableObject {
}

func handleConfirmTap() {
guard let selectedCoordinate = selectedDeviceLocation?.coordinates.toCLLocationCoordinate2D(),
guard let selectedCoordinate,
deviceLocationUseCase.areLocationCoordinatesValid(LocationCoordinates.fromCLLocationCoordinate2D(selectedCoordinate)) else {
Toast.shared.show(text: LocalizableString.invalidLocationErrorText.localized.attributedMarkdown ?? "")
return
Expand All @@ -53,14 +53,14 @@ class SelectStationLocationViewModel: ObservableObject {
}

extension SelectStationLocationViewModel: SelectLocationMapViewModelDelegate {
func updatedSelectedLocation(location: DeviceLocation?) {
self.selectedDeviceLocation = location
func updatedSelectedCoordinate(coordinate: CLLocationCoordinate2D?) {
self.selectedCoordinate = coordinate
}
}

private extension SelectStationLocationViewModel {
func setLocation() {
guard let deviceId = device.id, let selectedCoordinate = selectedDeviceLocation?.coordinates.toCLLocationCoordinate2D() else {
guard let deviceId = device.id, let selectedCoordinate else {
return
}

Expand Down
2 changes: 1 addition & 1 deletion ci_scripts/ci_post_clone.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ echo "password ${MAPBOX_TOKEN}" >> ~/.netrc
if ([ "$CI_WORKFLOW" = "QA Production" ]) || ([ "$CI_WORKFLOW" = "QA Dev" ]) || ([ "$CI_WORKFLOW" = "Dev Build" ]);
then
echo "Install Firebase CLI"
curl -Lo ./firebase-tools-macos https://firebase.tools/bin/macos/latest
curl -Lo ./firebase-tools-macos https://github.com/firebase/firebase-tools/releases/download/v13.16.0/firebase-tools-macos
chmod +x ./firebase-tools-macos

DEBUG_CONFIGURATION_PATH=${CI_PRIMARY_REPOSITORY_PATH}/Configuration/Debug/ConfigDebug.xcconfig
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public class DeviceLocationRepositoryImpl: DeviceLocationRepository {
return
}

self.reverseGeocodedAddressSubject.send(actualAddress.toLocation())
self.reverseGeocodedAddressSubject.send(actualAddress.toLocation(with: coordinates.toCLLocationCoordinate2D()))
case let .failure(error):
if let locationError = error.toDeviceLocationError() {
self.errorSubject.send(locationError)
Expand Down Expand Up @@ -190,21 +190,26 @@ extension SearchSuggestion {
}

extension SearchResult {
func toLocation() -> DeviceLocation {
var parsedAddress = name

if let houseNumber = address?.houseNumber {
parsedAddress += " \(houseNumber)"
}
func toLocation(with locationCoordinate: CLLocationCoordinate2D? = nil) -> DeviceLocation {
let parsedAddress = isAccurate ? address?.formattedAddress(style: .medium) : nil

return DeviceLocation(
id: id,
name: parsedAddress,
country: address?.country,
countryCode: metadata?["iso_3166_1"],
coordinates: LocationCoordinates.fromCLLocationCoordinate2D(coordinate)
coordinates: LocationCoordinates.fromCLLocationCoordinate2D(locationCoordinate ?? coordinate)
)
}

var isAccurate: Bool {
switch accuracy {
case .point, .rooftop, .street:
true
default:
false
}
}
}

public extension LocationCoordinates {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ public struct DeviceLocationSearchResult: Identifiable, Equatable, Hashable {

public struct DeviceLocation: Identifiable, Equatable {
public let id: String
public let name: String
public let name: String?
public let country: String?
public let countryCode: String?
public let coordinates: LocationCoordinates

public init(id: String, name: String, country: String?, countryCode: String?, coordinates: LocationCoordinates) {
public init(id: String, name: String?, country: String?, countryCode: String?, coordinates: LocationCoordinates) {
self.id = id
self.name = name
self.country = country
Expand Down

0 comments on commit 5f71e62

Please sign in to comment.