11import Foundation
22import UIKit
3- import MapKit
4- import CoreLocation
53import NetworkingCore
64
75/// Helper class to handle opening addresses in Maps apps.
86final class OrderDetailsMapLauncher {
97 static func openAddress( _ address: Address , from viewController: UIViewController ) {
10- // Use custom URL scheme approach directly for better control and reliability
118 openWithCustomURLSchemes ( address: address, from: viewController)
129 }
10+ }
1311
14- /// Opens address using custom URL schemes with app selection
15- private static func openWithCustomURLSchemes( address: Address , from viewController: UIViewController ) {
12+ private extension OrderDetailsMapLauncher {
13+ /// Opens address using custom URL schemes with app selection if more than one maps app is available.
14+ static func openWithCustomURLSchemes( address: Address , from viewController: UIViewController ) {
1615 let addressString = formatAddressForMaps ( address)
17-
16+
1817 let appleURL = createAppleMapsURL ( from: addressString)
19-
18+
2019 // Checks availability for each app explicitly.
2120 var availableOptions : [ ( URL , String ) ] = [ ]
22-
21+
2322 if let appleURL = appleURL, UIApplication . shared. canOpenURL ( appleURL) {
24- availableOptions. append ( ( appleURL, " Apple Maps " ) )
23+ availableOptions. append ( ( appleURL, Localization . appleMaps ) )
2524 }
26-
27- // Tries to find an available Google Maps URL
25+
26+ // Tries to find an available Google Maps URL.
2827 if let googleURL = findAvailableGoogleMapsURL ( for: addressString) {
29- availableOptions. append ( ( googleURL, " Google Maps " ) )
28+ availableOptions. append ( ( googleURL, Localization . googleMaps ) )
3029 }
31-
30+
3231 guard !availableOptions. isEmpty else {
33- // Fallback to web-based maps if no apps are available
32+ // Fallback to web-based maps if no apps are available.
3433 if let webURL = createWebMapsURL ( from: addressString) {
3534 UIApplication . shared. open ( webURL)
3635 }
3736 return
3837 }
39-
38+
4039 if availableOptions. count == 1 {
41- // Only one option available, open directly
4240 UIApplication . shared. open ( availableOptions [ 0 ] . 0 )
4341 } else {
44- // Multiple options available, show action sheet
4542 showActionSheet ( options: availableOptions, from: viewController)
4643 }
4744 }
48-
49- private static func formatAddressForMaps( _ address: Address ) -> String {
45+
46+ static func formatAddressForMaps( _ address: Address ) -> String {
5047 return [
5148 address. address1,
5249 address. address2,
@@ -56,77 +53,82 @@ final class OrderDetailsMapLauncher {
5653 address. country
5754 ] . compactMap { $0? . isEmpty == false ? $0 : nil } . joined ( separator: " , " )
5855 }
59-
60- private static func createAppleMapsURL( from addressString: String ) -> URL ? {
56+
57+ static func createAppleMapsURL( from addressString: String ) -> URL ? {
6158 guard let encodedAddress = addressString. addingPercentEncoding ( withAllowedCharacters: . urlQueryAllowed) else {
6259 return nil
6360 }
6461 return URL ( string: " http://maps.apple.com/?q= \( encodedAddress) " )
6562 }
66-
67- private static func createGoogleMapsURL( from addressString: String ) -> URL ? {
68- guard let encodedAddress = addressString. addingPercentEncoding ( withAllowedCharacters: . urlQueryAllowed) else {
69- return nil
70- }
71- // Try the newer Google Maps URL scheme first
72- return URL ( string: " googlemaps://?q= \( encodedAddress) " )
73- }
74-
75- private static func findAvailableGoogleMapsURL( for addressString: String ) -> URL ? {
63+
64+ static func findAvailableGoogleMapsURL( for addressString: String ) -> URL ? {
7665 guard let encodedAddress = addressString. addingPercentEncoding ( withAllowedCharacters: . urlQueryAllowed) else {
7766 return nil
7867 }
79-
68+
8069 // Try different Google Maps URL schemes in order of preference
8170 let googleMapsSchemes = [
8271 " googlemaps://?q= \( encodedAddress) " , // Modern Google Maps
8372 " comgooglemaps://?q= \( encodedAddress) " , // Legacy Google Maps
8473 " gmap://?q= \( encodedAddress) " // Alternative scheme
8574 ]
86-
75+
8776 for schemeString in googleMapsSchemes {
8877 if let url = URL ( string: schemeString) , UIApplication . shared. canOpenURL ( url) {
8978 return url
9079 }
9180 }
92-
81+
9382 return nil
9483 }
95-
96- private static func createWebMapsURL( from addressString: String ) -> URL ? {
84+
85+ static func createWebMapsURL( from addressString: String ) -> URL ? {
9786 guard let encodedAddress = addressString. addingPercentEncoding ( withAllowedCharacters: . urlQueryAllowed) else {
9887 return nil
9988 }
10089 return URL ( string: " https://maps.google.com/maps?q= \( encodedAddress) " )
10190 }
102-
103- private static func showActionSheet( options: [ ( URL , String ) ] , from viewController: UIViewController ) {
91+
92+ static func showActionSheet( options: [ ( URL , String ) ] , from viewController: UIViewController ) {
10493 let alertController = UIAlertController (
10594 title: NSLocalizedString ( " Open Address " , comment: " Title for the action sheet to open address in maps " ) ,
10695 message: nil ,
10796 preferredStyle: . actionSheet
10897 )
109-
98+
11099 for (url, name) in options {
111100 let action = UIAlertAction ( title: name, style: . default) { _ in
112101 UIApplication . shared. open ( url)
113102 }
114103 alertController. addAction ( action)
115104 }
116-
105+
117106 let cancelAction = UIAlertAction (
118107 title: NSLocalizedString ( " Cancel " , comment: " Cancel action for opening address in maps " ) ,
119108 style: . cancel
120109 )
121110 alertController. addAction ( cancelAction)
122-
111+
123112 // For iPad support
124113 if let popover = alertController. popoverPresentationController {
125114 popover. sourceView = viewController. view
126115 popover. sourceRect = CGRect ( x: viewController. view. bounds. midX, y: viewController. view. bounds. midY, width: 0 , height: 0 )
127116 popover. permittedArrowDirections = [ ]
128117 }
129-
118+
130119 viewController. present ( alertController, animated: true )
131120 }
132121}
122+
123+ private enum Localization {
124+ static let appleMaps = NSLocalizedString (
125+ " orderDetails.mapLauncher.appleMaps " ,
126+ value: " Apple Maps " ,
127+ comment: " Name of Apple Maps app in action sheet "
128+ )
129+ static let googleMaps = NSLocalizedString (
130+ " orderDetails.mapLauncher.googleMaps " ,
131+ value: " Google Maps " ,
132+ comment: " Name of Google Maps app in action sheet "
133+ )
134+ }
0 commit comments