diff --git a/LocationServices/Gemfile.lock b/LocationServices/Gemfile.lock index 0a66f42c..a1bb8e3f 100644 --- a/LocationServices/Gemfile.lock +++ b/LocationServices/Gemfile.lock @@ -10,20 +10,20 @@ GEM artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.971.0) - aws-sdk-core (3.203.0) + aws-partitions (1.1013.0) + aws-sdk-core (3.214.0) aws-eventstream (~> 1, >= 1.3.0) - aws-partitions (~> 1, >= 1.651.0) + aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.89.0) - aws-sdk-core (~> 3, >= 3.203.0) + aws-sdk-kms (1.96.0) + aws-sdk-core (~> 3, >= 3.210.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.160.0) - aws-sdk-core (~> 3, >= 3.203.0) + aws-sdk-s3 (1.174.0) + aws-sdk-core (~> 3, >= 3.210.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) - aws-sigv4 (1.9.1) + aws-sigv4 (1.10.1) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) base64 (0.2.0) @@ -38,8 +38,8 @@ GEM domain_name (0.6.20240107) dotenv (2.8.1) emoji_regex (3.2.3) - excon (0.111.0) - faraday (1.10.3) + excon (0.112.0) + faraday (1.10.4) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) faraday-excon (~> 1.1) @@ -65,10 +65,10 @@ GEM faraday-patron (1.0.0) faraday-rack (1.0.0) faraday-retry (1.0.3) - faraday_middleware (1.2.0) + faraday_middleware (1.2.1) faraday (~> 1.0) fastimage (2.3.1) - fastlane (2.222.0) + fastlane (2.225.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -84,6 +84,7 @@ GEM faraday-cookie_jar (~> 0.0.6) faraday_middleware (~> 1.0) fastimage (>= 2.1.0, < 3.0.0) + fastlane-sirp (>= 1.0.0) gh_inspector (>= 1.1.2, < 2.0.0) google-apis-androidpublisher_v3 (~> 0.3) google-apis-playcustomapp_v1 (~> 0.1) @@ -109,6 +110,8 @@ GEM xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) + fastlane-sirp (1.0.0) + sysrandom (~> 1.0) gh_inspector (1.1.3) google-apis-androidpublisher_v3 (0.54.0) google-apis-core (>= 0.11.0, < 2.a) @@ -151,17 +154,17 @@ GEM domain_name (~> 0.5) httpclient (2.8.3) jmespath (1.6.2) - json (2.7.2) - jwt (2.8.2) + json (2.8.2) + jwt (2.9.3) base64 mini_magick (4.13.2) mini_mime (1.1.5) multi_json (1.15.0) multipart-post (2.4.1) - nanaimo (0.3.0) + nanaimo (0.4.0) naturally (2.2.1) nkf (0.2.0) - optparse (0.5.0) + optparse (0.6.0) os (1.1.4) plist (3.7.1) public_suffix (6.0.1) @@ -171,7 +174,7 @@ GEM trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) - rexml (3.3.7) + rexml (3.3.9) rouge (2.0.7) ruby2_keywords (0.0.5) rubyzip (2.3.2) @@ -185,6 +188,7 @@ GEM CFPropertyList naturally slack-notifier (2.4.0) + sysrandom (1.0.5) terminal-notifier (2.0.0) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) @@ -194,15 +198,15 @@ GEM tty-spinner (0.9.3) tty-cursor (~> 0.7) uber (0.1.0) - unicode-display_width (2.5.0) + unicode-display_width (2.6.0) word_wrap (1.0.0) - xcodeproj (1.25.0) + xcodeproj (1.27.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) colored2 (~> 3.1) - nanaimo (~> 0.3.0) - rexml (>= 3.3.2, < 4.0) + nanaimo (~> 0.4.0) + rexml (>= 3.3.6, < 4.0) xcov (1.8.1) fastlane (>= 2.141.0, < 3.0.0) multipart-post diff --git a/LocationServices/LocationServices.xcodeproj/project.pbxproj b/LocationServices/LocationServices.xcodeproj/project.pbxproj index d2b1424b..de16f285 100644 --- a/LocationServices/LocationServices.xcodeproj/project.pbxproj +++ b/LocationServices/LocationServices.xcodeproj/project.pbxproj @@ -357,6 +357,9 @@ F11E045E2CD509A2003F1641 /* AmazonLocationiOSAuthSDK in Frameworks */ = {isa = PBXBuildFile; productRef = F11E045D2CD509A2003F1641 /* AmazonLocationiOSAuthSDK */; }; F11E04612CD515C0003F1641 /* KeychainSwift in Frameworks */ = {isa = PBXBuildFile; productRef = F11E04602CD515C0003F1641 /* KeychainSwift */; }; F11E04632CD516DD003F1641 /* KeyChainHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F11E04622CD516DD003F1641 /* KeyChainHelper.swift */; }; + F11E046F2CE788EA003F1641 /* LanguageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F11E046E2CE788DA003F1641 /* LanguageView.swift */; }; + F11E04712CE788FD003F1641 /* LanguageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F11E04702CE788F3003F1641 /* LanguageViewController.swift */; }; + F11E04732CE791A3003F1641 /* LanguageViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F11E04722CE791A1003F1641 /* LanguageViewCell.swift */; }; F139208829EE918E0042CBC9 /* AWSLocationTravelModeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F139208429EE918E0042CBC9 /* AWSLocationTravelModeTests.swift */; }; F139208929EE918E0042CBC9 /* CLLocationCoordinate2DExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F139208529EE918E0042CBC9 /* CLLocationCoordinate2DExtensionTests.swift */; }; F139208A29EE918E0042CBC9 /* CLLocationExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F139208629EE918E0042CBC9 /* CLLocationExtensionTests.swift */; }; @@ -779,6 +782,9 @@ F10994F929D1C834001D3464 /* UITestSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestSettingsScreen.swift; sourceTree = ""; }; F111DF0E29F0214B00D08641 /* MapStyleViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapStyleViewModelTests.swift; sourceTree = ""; }; F11E04622CD516DD003F1641 /* KeyChainHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyChainHelper.swift; sourceTree = ""; }; + F11E046E2CE788DA003F1641 /* LanguageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LanguageView.swift; sourceTree = ""; }; + F11E04702CE788F3003F1641 /* LanguageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LanguageViewController.swift; sourceTree = ""; }; + F11E04722CE791A1003F1641 /* LanguageViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LanguageViewCell.swift; sourceTree = ""; }; F139208429EE918E0042CBC9 /* AWSLocationTravelModeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AWSLocationTravelModeTests.swift; sourceTree = ""; }; F139208529EE918E0042CBC9 /* CLLocationCoordinate2DExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CLLocationCoordinate2DExtensionTests.swift; sourceTree = ""; }; F139208629EE918E0042CBC9 /* CLLocationExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CLLocationExtensionTests.swift; sourceTree = ""; }; @@ -2260,6 +2266,8 @@ children = ( ADBDDF062984392A00696EC6 /* Cell */, ADBDDF022984386400696EC6 /* ExploreMapStyleHeaderView.swift */, + F11E046E2CE788DA003F1641 /* LanguageView.swift */, + F11E04702CE788F3003F1641 /* LanguageViewController.swift */, F1C4DC672CC7BD7100AA235A /* PoliticalView.swift */, F1C4DC632CC7ADCE00AA235A /* PoliticalViewController.swift */, F1C4DC532CC1614800AA235A /* ColorSegmentControl.swift */, @@ -2279,6 +2287,7 @@ ADBDDF062984392A00696EC6 /* Cell */ = { isa = PBXGroup; children = ( + F11E04722CE791A1003F1641 /* LanguageViewCell.swift */, F1C4DC652CC7BA9D00AA235A /* PoliticalViewCell.swift */, ADBDDF072984394500696EC6 /* ExploreMapStyleCell.swift */, ); @@ -3283,6 +3292,7 @@ F1CB5B5C2A4486F200A346F5 /* GridBackgroundView.swift in Sources */, ADD139952980A34E0003F917 /* RouteOptionRowView.swift in Sources */, ADD5D7B1296E00340022480B /* PostLoginView.swift in Sources */, + F11E046F2CE788EA003F1641 /* LanguageView.swift in Sources */, ADD1396A2980966E0003F917 /* DataProviderVC.swift in Sources */, 8A75093729EEE1D100B9985F /* NumberConstants.swift in Sources */, ADD1395A2980874A0003F917 /* UnitSceneViewModel.swift in Sources */, @@ -3408,6 +3418,7 @@ 8ACAAD7629F14B9D00523256 /* CLLocationManager+Extension.swift in Sources */, AD2AF0EB292EAEDF00149904 /* AppColorsConstants.swift in Sources */, AD2AF030292E892000149904 /* AppDelegate.swift in Sources */, + F11E04732CE791A3003F1641 /* LanguageViewCell.swift in Sources */, AD2AF0CF292EAB9000149904 /* SettingsContracts.swift in Sources */, AD33F4C52950FE03005719D3 /* DirectionSearchView.swift in Sources */, ADAE4FFD2935734E0000F7FC /* String+Extensions.swift in Sources */, @@ -3445,6 +3456,7 @@ ADABECDE293FE8F200E66FC5 /* SearchVCContracts.swift in Sources */, AD625EA5293CDC5500C67B44 /* Endpoint.swift in Sources */, ADD1398E2980A24E0003F917 /* RouteOptionViewModel.swift in Sources */, + F11E04712CE788FD003F1641 /* LanguageViewController.swift in Sources */, ADD5D7E52970A9EB0022480B /* AddGeofenceMessageTextField.swift in Sources */, AD2AF095292EA8A800149904 /* GeofenceVC.swift in Sources */, AD989727298B0A250041E867 /* CommonDashboardView.swift in Sources */, @@ -3634,6 +3646,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = ""; @@ -3901,6 +3914,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = ""; diff --git a/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationCarIcon.imageset/Contents.json b/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationCarIcon.imageset/Contents.json deleted file mode 100644 index 6023466a..00000000 --- a/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationCarIcon.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images" : [ - { - "filename" : "icon-car-solid.svg", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationCarIcon.imageset/icon-car-solid.svg b/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationCarIcon.imageset/icon-car-solid.svg deleted file mode 100644 index 230bdf57..00000000 --- a/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationCarIcon.imageset/icon-car-solid.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - icon-car-solid - - - - - - - - - - \ No newline at end of file diff --git a/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationTruckIcon.imageset/Contents.json b/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationTruckIcon.imageset/Contents.json deleted file mode 100644 index e26078e9..00000000 --- a/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationTruckIcon.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images" : [ - { - "filename" : "icon-truck-solid.svg", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationTruckIcon.imageset/icon-truck-solid.svg b/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationTruckIcon.imageset/icon-truck-solid.svg deleted file mode 100644 index 48daed71..00000000 --- a/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationTruckIcon.imageset/icon-truck-solid.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - icon-truck-solid - - - - - - - - - - \ No newline at end of file diff --git a/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationWalkingIcon.imageset/Contents.json b/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationWalkingIcon.imageset/Contents.json deleted file mode 100644 index 32d68b67..00000000 --- a/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationWalkingIcon.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images" : [ - { - "filename" : "icon-person-walking-solid.svg", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationWalkingIcon.imageset/icon-person-walking-solid.svg b/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationWalkingIcon.imageset/icon-person-walking-solid.svg deleted file mode 100644 index e7548367..00000000 --- a/LocationServices/LocationServices/Assets.xcassets/NavigationIcons/navigationWalkingIcon.imageset/icon-person-walking-solid.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - icon-person-walking-solid - - - - - - - - - - \ No newline at end of file diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/contrast_map_layer.imageset/Preview.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/contrast_map_layer.imageset/Preview.png deleted file mode 100644 index 6960b10a..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/contrast_map_layer.imageset/Preview.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/contrast_map_layer.imageset/Preview@2x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/contrast_map_layer.imageset/Preview@2x.png deleted file mode 100644 index 029dbc86..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/contrast_map_layer.imageset/Preview@2x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/contrast_map_layer.imageset/Preview@3x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/contrast_map_layer.imageset/Preview@3x.png deleted file mode 100644 index 78ab51f1..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/contrast_map_layer.imageset/Preview@3x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/dark_gray_map_layer.imageset/Preview.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/dark_gray_map_layer.imageset/Preview.png deleted file mode 100644 index 02524423..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/dark_gray_map_layer.imageset/Preview.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/dark_gray_map_layer.imageset/Preview@2x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/dark_gray_map_layer.imageset/Preview@2x.png deleted file mode 100644 index d902fef8..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/dark_gray_map_layer.imageset/Preview@2x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/dark_gray_map_layer.imageset/Preview@3x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/dark_gray_map_layer.imageset/Preview@3x.png deleted file mode 100644 index a39139ed..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/dark_gray_map_layer.imageset/Preview@3x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/esri_imagerey.imageset/Preview.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/esri_imagerey.imageset/Preview.png deleted file mode 100644 index d879da3b..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/esri_imagerey.imageset/Preview.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/esri_imagerey.imageset/Preview@2x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/esri_imagerey.imageset/Preview@2x.png deleted file mode 100644 index 520e8c8d..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/esri_imagerey.imageset/Preview@2x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/esri_imagerey.imageset/Preview@3x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/esri_imagerey.imageset/Preview@3x.png deleted file mode 100644 index 75f9ebf0..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/esri_imagerey.imageset/Preview@3x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_map_layer.imageset/Preview.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_map_layer.imageset/Preview.png deleted file mode 100644 index c6a18456..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_map_layer.imageset/Preview.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_map_layer.imageset/Preview@2x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_map_layer.imageset/Preview@2x.png deleted file mode 100644 index 2dc14e34..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_map_layer.imageset/Preview@2x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_map_layer.imageset/Preview@3x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_map_layer.imageset/Preview@3x.png deleted file mode 100644 index ca656081..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_map_layer.imageset/Preview@3x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_truck_map_layer.imageset/Contents.json b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_truck_map_layer.imageset/Contents.json deleted file mode 100644 index afedb4a7..00000000 --- a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_truck_map_layer.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "Preview.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Preview@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Preview@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_truck_map_layer.imageset/Preview.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_truck_map_layer.imageset/Preview.png deleted file mode 100644 index 53d8e6fc..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_truck_map_layer.imageset/Preview.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_truck_map_layer.imageset/Preview@2x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_truck_map_layer.imageset/Preview@2x.png deleted file mode 100644 index 8dcc77ef..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_truck_map_layer.imageset/Preview@2x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_truck_map_layer.imageset/Preview@3x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_truck_map_layer.imageset/Preview@3x.png deleted file mode 100644 index 50e3d1c9..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_truck_map_layer.imageset/Preview@3x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/here_imagerey_map_layer.imageset/Contents.json b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/here_imagerey_map_layer.imageset/Contents.json deleted file mode 100644 index afedb4a7..00000000 --- a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/here_imagerey_map_layer.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "Preview.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Preview@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Preview@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/here_imagerey_map_layer.imageset/Preview.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/here_imagerey_map_layer.imageset/Preview.png deleted file mode 100644 index f2752c1c..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/here_imagerey_map_layer.imageset/Preview.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/here_imagerey_map_layer.imageset/Preview@2x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/here_imagerey_map_layer.imageset/Preview@2x.png deleted file mode 100644 index 63c9534c..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/here_imagerey_map_layer.imageset/Preview@2x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/here_imagerey_map_layer.imageset/Preview@3x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/here_imagerey_map_layer.imageset/Preview@3x.png deleted file mode 100644 index b5cb30b1..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/here_imagerey_map_layer.imageset/Preview@3x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybird_map_layer.imageset/Contents.json b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybird_map_layer.imageset/Contents.json deleted file mode 100644 index afedb4a7..00000000 --- a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybird_map_layer.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "Preview.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Preview@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Preview@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybird_map_layer.imageset/Preview.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybird_map_layer.imageset/Preview.png deleted file mode 100644 index 35ec344a..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybird_map_layer.imageset/Preview.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybird_map_layer.imageset/Preview@2x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybird_map_layer.imageset/Preview@2x.png deleted file mode 100644 index 62f6043a..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybird_map_layer.imageset/Preview@2x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybird_map_layer.imageset/Preview@3x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybird_map_layer.imageset/Preview@3x.png deleted file mode 100644 index d5829f08..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybird_map_layer.imageset/Preview@3x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/dark_gray_map_layer.imageset/Contents.json b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybrid_map_layer.imageset/Contents.json similarity index 71% rename from LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/dark_gray_map_layer.imageset/Contents.json rename to LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybrid_map_layer.imageset/Contents.json index afedb4a7..a8113a0f 100644 --- a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/dark_gray_map_layer.imageset/Contents.json +++ b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybrid_map_layer.imageset/Contents.json @@ -1,17 +1,15 @@ { "images" : [ { - "filename" : "Preview.png", + "filename" : "hybrid_map_layer.png", "idiom" : "universal", "scale" : "1x" }, { - "filename" : "Preview@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Preview@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybrid_map_layer.imageset/hybrid_map_layer.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybrid_map_layer.imageset/hybrid_map_layer.png new file mode 100644 index 00000000..10f246ab Binary files /dev/null and b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/hybrid_map_layer.imageset/hybrid_map_layer.png differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_gray_map_layer.imageset/Contents.json b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_gray_map_layer.imageset/Contents.json deleted file mode 100644 index afedb4a7..00000000 --- a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_gray_map_layer.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "Preview.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Preview@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Preview@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_gray_map_layer.imageset/Preview.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_gray_map_layer.imageset/Preview.png deleted file mode 100644 index a7a7963b..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_gray_map_layer.imageset/Preview.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_gray_map_layer.imageset/Preview@2x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_gray_map_layer.imageset/Preview@2x.png deleted file mode 100644 index d6726c07..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_gray_map_layer.imageset/Preview@2x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_gray_map_layer.imageset/Preview@3x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_gray_map_layer.imageset/Preview@3x.png deleted file mode 100644 index 27ff9858..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_gray_map_layer.imageset/Preview@3x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_map_layer.imageset/Contents.json b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_map_layer.imageset/Contents.json deleted file mode 100644 index afedb4a7..00000000 --- a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_map_layer.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "Preview.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Preview@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Preview@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_map_layer.imageset/Preview.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_map_layer.imageset/Preview.png deleted file mode 100644 index 91dc04a4..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_map_layer.imageset/Preview.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_map_layer.imageset/Preview@2x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_map_layer.imageset/Preview@2x.png deleted file mode 100644 index b7183952..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_map_layer.imageset/Preview@2x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_map_layer.imageset/Preview@3x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_map_layer.imageset/Preview@3x.png deleted file mode 100644 index 421fcf00..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/light_map_layer.imageset/Preview@3x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/esri_imagerey.imageset/Contents.json b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/monochrome_map_layer.imageset/Contents.json similarity index 71% rename from LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/esri_imagerey.imageset/Contents.json rename to LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/monochrome_map_layer.imageset/Contents.json index afedb4a7..29f21d40 100644 --- a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/esri_imagerey.imageset/Contents.json +++ b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/monochrome_map_layer.imageset/Contents.json @@ -1,17 +1,15 @@ { "images" : [ { - "filename" : "Preview.png", + "filename" : "monochrome_map_layer.png", "idiom" : "universal", "scale" : "1x" }, { - "filename" : "Preview@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Preview@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/monochrome_map_layer.imageset/monochrome_map_layer.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/monochrome_map_layer.imageset/monochrome_map_layer.png new file mode 100644 index 00000000..ce8aabc0 Binary files /dev/null and b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/monochrome_map_layer.imageset/monochrome_map_layer.png differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/navigation_map_layer.imageset/Contents.json b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/navigation_map_layer.imageset/Contents.json deleted file mode 100644 index afedb4a7..00000000 --- a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/navigation_map_layer.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "Preview.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Preview@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Preview@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/navigation_map_layer.imageset/Preview.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/navigation_map_layer.imageset/Preview.png deleted file mode 100644 index a73e82f8..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/navigation_map_layer.imageset/Preview.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/navigation_map_layer.imageset/Preview@2x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/navigation_map_layer.imageset/Preview@2x.png deleted file mode 100644 index 88533a03..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/navigation_map_layer.imageset/Preview@2x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/navigation_map_layer.imageset/Preview@3x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/navigation_map_layer.imageset/Preview@3x.png deleted file mode 100644 index 2c04c784..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/navigation_map_layer.imageset/Preview@3x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_map_layer.imageset/Contents.json b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/satellite_map_layer.imageset/Contents.json similarity index 71% rename from LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_map_layer.imageset/Contents.json rename to LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/satellite_map_layer.imageset/Contents.json index afedb4a7..7f35c9d7 100644 --- a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/explore_map_layer.imageset/Contents.json +++ b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/satellite_map_layer.imageset/Contents.json @@ -1,17 +1,15 @@ { "images" : [ { - "filename" : "Preview.png", + "filename" : "satellite_map_layer.png", "idiom" : "universal", "scale" : "1x" }, { - "filename" : "Preview@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Preview@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/satellite_map_layer.imageset/satellite_map_layer.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/satellite_map_layer.imageset/satellite_map_layer.png new file mode 100644 index 00000000..10f60869 Binary files /dev/null and b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/satellite_map_layer.imageset/satellite_map_layer.png differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/contrast_map_layer.imageset/Contents.json b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/standard_map_layer.imageset/Contents.json similarity index 71% rename from LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/contrast_map_layer.imageset/Contents.json rename to LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/standard_map_layer.imageset/Contents.json index afedb4a7..8716d447 100644 --- a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/contrast_map_layer.imageset/Contents.json +++ b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/standard_map_layer.imageset/Contents.json @@ -1,17 +1,15 @@ { "images" : [ { - "filename" : "Preview.png", + "filename" : "standard_map_layer.png", "idiom" : "universal", "scale" : "1x" }, { - "filename" : "Preview@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Preview@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/standard_map_layer.imageset/standard_map_layer.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/standard_map_layer.imageset/standard_map_layer.png new file mode 100644 index 00000000..379ebb71 Binary files /dev/null and b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/standard_map_layer.imageset/standard_map_layer.png differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/street_map_layer.imageset/Contents.json b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/street_map_layer.imageset/Contents.json deleted file mode 100644 index afedb4a7..00000000 --- a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/street_map_layer.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "Preview.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Preview@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Preview@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/street_map_layer.imageset/Preview.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/street_map_layer.imageset/Preview.png deleted file mode 100644 index 6138b949..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/street_map_layer.imageset/Preview.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/street_map_layer.imageset/Preview@2x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/street_map_layer.imageset/Preview@2x.png deleted file mode 100644 index f210e9fa..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/street_map_layer.imageset/Preview@2x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/street_map_layer.imageset/Preview@3x.png b/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/street_map_layer.imageset/Preview@3x.png deleted file mode 100644 index 4b605d6d..00000000 Binary files a/LocationServices/LocationServices/Assets.xcassets/Settings Icons/MapLayerImages/street_map_layer.imageset/Preview@3x.png and /dev/null differ diff --git a/LocationServices/LocationServices/Constants/AppIconConstants.swift b/LocationServices/LocationServices/Constants/AppIconConstants.swift index c81fd667..c3586af8 100644 --- a/LocationServices/LocationServices/Constants/AppIconConstants.swift +++ b/LocationServices/LocationServices/Constants/AppIconConstants.swift @@ -32,14 +32,15 @@ extension UIImage { static let annotationIcon = UIImage(named: "annotation-icon")! static let selectedPlace = UIImage(named: "selected-place")! static let stepIcon = UIImage(named: "step-icon")! - static let carIcon = UIImage(named: "icon-car-solid")! + static let carIcon = UIImage(systemName: "car.fill")! static let closeIcon = UIImage(named: "icon-close")! static let swapDestinations = UIImage(named: "swapDestinations")! static let myLocationIcon = UIImage(named: "mylocation-icon")! - static let navigationCarIcon = UIImage(named: "navigationCarIcon")! - static let navigationWalkingIcon = UIImage(named: "navigationWalkingIcon")! - static let navigationTruckIcon = UIImage(named: "navigationTruckIcon")! + static let navigationCarIcon = UIImage(systemName: "car.fill")! + static let navigationWalkingIcon = UIImage(systemName: "figure.walk")! + static let navigationScooterIcon = UIImage(systemName: "scooter")! + static let navigationTruckIcon = UIImage(systemName: "truck.box.fill")! static let navigationDashedIcon = UIImage(named: "navigationDashedIcon")! static let loginLogo = UIImage(named: "login-logo") @@ -57,23 +58,19 @@ extension UIImage { static let disconnectIcon = UIImage(named: "icon-disconnect")! /// Map Layer - static let contrastMapLayer = UIImage(named: "contrast_map_layer")! - static let exploreMapLayer = UIImage(named: "explore_map_layer")! - static let lightMapLayer = UIImage(named: "light_map_layer")! - static let navigationMapLayer = UIImage(named: "navigation_map_layer")! - static let streetMapLayer = UIImage(named: "street_map_layer")! - static let esri_imagerey = UIImage(named: "esri_imagerey")! - static let explore_truck_map_layer = UIImage(named: "explore_truck_map_layer")! - static let here_imagerey_map_layer = UIImage(named: "here_imagerey_map_layer")! - static let hybird_map_layer = UIImage(named: "hybird_map_layer")! - static let light_gray_map_layer = UIImage(named: "light_gray_map_layer")! - static let dark_gray_map_layer = UIImage(named: "dark_gray_map_layer")! + static let standardMapLayer = UIImage(named: "standard_map_layer")! + static let monochromeMapLayer = UIImage(named: "monochrome_map_layer")! + static let satelliteMapLayer = UIImage(named: "satellite_map_layer")! + static let hybridMapLayer = UIImage(named: "hybrid_map_layer")! static let trashIcon = UIImage(named: "icon-trash")! static let geofenceDashoard = UIImage(named: "geofence-dashboard")! static let alertTriangleSolid = UIImage(named: "alert-triangle-solid")! static let infoIcon = UIImage(named: "info-icon") static let logoPoweredByAWS = UIImage(named: "logo-powered-by-aws") + static let expandUpIcon = UIImage(systemName: "chevron.up") + static let expandDownIcon = UIImage(systemName: "chevron.down") + static let copyIcon = UIImage(systemName: "clipboard") //system static let sidebarLeft = UIImage(systemName: "sidebar.left") diff --git a/LocationServices/LocationServices/Constants/StringConstants.swift b/LocationServices/LocationServices/Constants/StringConstants.swift index 02237df3..1313c0fd 100644 --- a/LocationServices/LocationServices/Constants/StringConstants.swift +++ b/LocationServices/LocationServices/Constants/StringConstants.swift @@ -48,7 +48,7 @@ enum StringConstant { // strings: - static let direction = "Direction" + static let direction = "Directions" static let directions = "Directions" static let geofence = "Geofence" static let login = "Login" diff --git a/LocationServices/LocationServices/Constants/ViewsIdentifiers.swift b/LocationServices/LocationServices/Constants/ViewsIdentifiers.swift index 467c4cbd..7df2ea30 100644 --- a/LocationServices/LocationServices/Constants/ViewsIdentifiers.swift +++ b/LocationServices/LocationServices/Constants/ViewsIdentifiers.swift @@ -35,6 +35,12 @@ struct ViewsIdentifiers { static let politicalViewCell = "politicalViewCell" static let politicalViewSubtitle = "politicalViewSubtitle" static let politicalViewCloseButton = "politicalViewCloseButton" + + static let languageViewTable = "languageViewTable" + static let languageViewCell = "languageViewCell" + static let languageViewButton = "languageViewButton" + static let languageViewSubtitle = "languageViewSubtitle" + static let languageViewCloseButton = "politicalViewCloseButton" } struct Explore { @@ -66,6 +72,7 @@ struct ViewsIdentifiers { static let carContainer = "CarContainer" static let pedestrianContainer = "pedestrianContainer" + static let scooterContainer = "scooterContainer" static let truckContainer = "TruckContainer" static let routeEstimatedTime = "RouteEstimatedTime" diff --git a/LocationServices/LocationServices/Coordinators/ChildCoordinators/ExploreCoordinator.swift b/LocationServices/LocationServices/Coordinators/ChildCoordinators/ExploreCoordinator.swift index f8e03d72..1995bcee 100644 --- a/LocationServices/LocationServices/Coordinators/ChildCoordinators/ExploreCoordinator.swift +++ b/LocationServices/LocationServices/Coordinators/ChildCoordinators/ExploreCoordinator.swift @@ -44,8 +44,9 @@ extension ExploreCoordinator: ExploreNavigationDelegate { } currentBottomSheet?.dismissBottomSheet() controller.presentBottomSheet(parentController: ExploreCoordinator.exploreController!) - controller.setBottomSheetHeight(to: controller.getLargeDetentHeight()) + controller.setBottomSheetHeight(to: 600) currentBottomSheet = controller + NotificationCenter.default.post(name: Notification.updateMapLayerItems, object: nil, userInfo: ["height": 500]) } func showDirections(isRouteOptionEnabled: Bool?, @@ -119,7 +120,7 @@ extension ExploreCoordinator: ExploreNavigationDelegate { controller.userLocation = (lat, long) currentBottomSheet?.dismissBottomSheet() controller.presentBottomSheet(parentController: ExploreCoordinator.exploreController!) - controller.setBottomSheetHeight(to: 200) + controller.setBottomSheetHeight(to: 450) currentBottomSheet = controller } diff --git a/LocationServices/LocationServices/Extensions/CLLocationCoordinate2D+Extension.swift b/LocationServices/LocationServices/Extensions/CLLocationCoordinate2D+Extension.swift index 6bfcc08b..838ff620 100644 --- a/LocationServices/LocationServices/Extensions/CLLocationCoordinate2D+Extension.swift +++ b/LocationServices/LocationServices/Extensions/CLLocationCoordinate2D+Extension.swift @@ -46,3 +46,8 @@ extension CLLocationCoordinate2D: Hashable { hasher.combine(longitude) } } + +struct LocationCoordinate2D: Codable { + var latitude: Double + var longitude: Double +} diff --git a/LocationServices/LocationServices/Extensions/Locale+Extension.swift b/LocationServices/LocationServices/Extensions/Locale+Extension.swift index 112c44ef..b9e3652f 100644 --- a/LocationServices/LocationServices/Extensions/Locale+Extension.swift +++ b/LocationServices/LocationServices/Extensions/Locale+Extension.swift @@ -9,6 +9,10 @@ import Foundation extension Locale { static func currentLanguageIdentifier() -> String { - return String((Locale.preferredLanguages.first ?? Locale.current.identifier).prefix(2)) + return (UserDefaultsHelper.getObject(value: LanguageSwitcherData.self, key: .language)?.value) ?? String(( Locale.preferredLanguages.first ?? Locale.current.identifier).prefix(2)) + } + + static func currentLanguageLabel() -> String { + return (UserDefaultsHelper.getObject(value: LanguageSwitcherData.self, key: .language)?.label) ?? String(( Locale.preferredLanguages.first ?? Locale.current.identifier)) } } diff --git a/LocationServices/LocationServices/Extensions/RouteTravelMode+Extension.swift b/LocationServices/LocationServices/Extensions/RouteTravelMode+Extension.swift index d5bd5e82..da18117d 100644 --- a/LocationServices/LocationServices/Extensions/RouteTravelMode+Extension.swift +++ b/LocationServices/LocationServices/Extensions/RouteTravelMode+Extension.swift @@ -17,6 +17,8 @@ extension GeoRoutesClientTypes.RouteTravelMode { self = .car case .truck: self = .truck + case .scooter: + self = .scooter } } } diff --git a/LocationServices/LocationServices/Helpers/GeneralHelper.swift b/LocationServices/LocationServices/Helpers/GeneralHelper.swift index dde49ba2..fef9dcdd 100644 --- a/LocationServices/LocationServices/Helpers/GeneralHelper.swift +++ b/LocationServices/LocationServices/Helpers/GeneralHelper.swift @@ -7,6 +7,7 @@ import Foundation import UIKit +import MapLibre class GeneralHelper { static func getAmazonMapLogo() -> UIColor { @@ -55,4 +56,59 @@ class GeneralHelper { image.withRenderingMode(.alwaysTemplate).draw(in: rect) } } + + static func setMapLanguage(mapView: MLNMapView, style: MLNStyle) { + let language = Locale.currentLanguageIdentifier() + + style.localizeLabels(into: Locale(identifier: language)) + + style.layers.forEach { layer in + guard let symbolLayer = layer as? MLNSymbolStyleLayer, + let textExpression = symbolLayer.text else { return } + let exp = "\(String(describing: symbolLayer.text))" + if exp.contains("MLN_IF(") { + return + } + let mglExpression = textExpression.mgl_jsonExpressionObject + let expression = recurseExpression(exp: mglExpression, prevPropertyRegex: "^name:([A-Za-z\\-_]+)$", nextProperty: "name:\(language)", language: language) + symbolLayer.text = NSExpression(mglJSONObject: expression) + } + } + + static func recurseExpression(exp: Any, prevPropertyRegex: String, nextProperty: String, language: String) -> Any { + if language == "zh-Hant" { + // Special handling for zh-Hant + return [ + "coalesce", + ["get", "name:zh-Hant"], + ["get", "name:zh"], + ["get", "name:en"], + ["get", "name"] + ] + } + + if let arrayExp = exp as? [Any] { + guard arrayExp.first as? String == "coalesce" else { + return arrayExp.map { recurseExpression(exp: $0, prevPropertyRegex: prevPropertyRegex, nextProperty: nextProperty, language: language) } + } + + guard arrayExp.count > 2, + let first = arrayExp[1] as? [Any], first.first as? String == "get", + let firstProperty = first.last as? String, + let _ = firstProperty.range(of: prevPropertyRegex, options: .regularExpression), + let second = arrayExp[2] as? [Any], second.first as? String == "get" else { + return arrayExp.map { recurseExpression(exp: $0, prevPropertyRegex: prevPropertyRegex, nextProperty: nextProperty, language: language) } + } + + return [ + "coalesce", + ["get", nextProperty], + ["get", "name:en"], + ["get", "name"] + ] + } + + return exp + } + } diff --git a/LocationServices/LocationServices/Helpers/UserDefaultsHelper.swift b/LocationServices/LocationServices/Helpers/UserDefaultsHelper.swift index 8c68fb5a..cdad2f4e 100644 --- a/LocationServices/LocationServices/Helpers/UserDefaultsHelper.swift +++ b/LocationServices/LocationServices/Helpers/UserDefaultsHelper.swift @@ -16,6 +16,7 @@ enum UserDefaultKeyType: String { case mapStyle case mapStyleColorType case politicalView + case language case tollOptions case ferriesOptions // means we attach the policy to AWSLocation for tracking @@ -31,6 +32,8 @@ enum UserDefaultKeyType: String { case appState case termsAndConditionsAgreedVersion case signedInIdentityId + + case mapCenter } enum AppState: Int { diff --git a/LocationServices/LocationServices/Models/MapModel.swift b/LocationServices/LocationServices/Models/MapModel.swift index 1ba82af0..526993ae 100644 --- a/LocationServices/LocationServices/Models/MapModel.swift +++ b/LocationServices/LocationServices/Models/MapModel.swift @@ -6,6 +6,7 @@ // SPDX-License-Identifier: MIT-0 import Foundation +import AWSGeoPlaces struct MapModel { let placeId: String? @@ -17,6 +18,11 @@ struct MapModel { let placeLong: Double? var distance: Double? var duration: String? + var place: GetPlaceOutput? = nil + let placeType: GeoPlacesClientTypes.PlaceType? + let queryType: GeoPlacesClientTypes.QueryType? + let suggestType: GeoPlacesClientTypes.SuggestResultItemType? + let queryId: String? init(placeId: String? = nil, placeName: String? = nil, placeAddress: String? = nil, placeCity: String? = nil, placeCountry: String? = nil, placeLat: Double? = nil, placeLong: Double? = nil, distance: Double? = nil, duration: String? = nil) { self.placeId = placeId @@ -28,6 +34,10 @@ struct MapModel { self.placeLong = placeLong self.distance = distance self.duration = duration + self.placeType = nil + self.queryType = nil + self.suggestType = nil + self.queryId = nil } init(model: SearchPresentation) { @@ -40,5 +50,10 @@ struct MapModel { self.placeLong = model.placeLong self.distance = model.distance self.duration = nil + self.place = model.place + self.placeType = model.placeType + self.queryType = model.queryType + self.suggestType = model.suggestType + self.queryId = model.queryId } } diff --git a/LocationServices/LocationServices/Networking/Services/LocationServiceable.swift b/LocationServices/LocationServices/Networking/Services/LocationServiceable.swift index 2c221817..b1f7e0ee 100644 --- a/LocationServices/LocationServices/Networking/Services/LocationServiceable.swift +++ b/LocationServices/LocationServices/Networking/Services/LocationServiceable.swift @@ -7,21 +7,21 @@ import Foundation import CoreLocation -import AWSLocation +import AWSGeoPlaces protocol LocationServiceable { - func searchText(text: String, userLat: Double?, userLong: Double?) async -> Result<[SearchPresentation], Error> + func searchText(text: String, userLat: Double?, userLong: Double?, queryId: String?) async -> Result<[SearchPresentation], Error> func searchWithSuggest(text: String, userLat: Double?, userLong: Double?) async -> Result<[SearchPresentation], Error> func reverseGeocode(position: [Double], userLat: Double?, userLong: Double?) async -> Result<[SearchPresentation], Error> - func getPlace(with placeId: String) async throws -> SearchPresentation? + func getPlace(with placeId: String) async throws -> GetPlaceOutput? } struct LocationService: AWSLocationSearchService, LocationServiceable { - func searchText(text: String, userLat: Double?, userLong: Double?) async -> Result<[SearchPresentation], Error> { + func searchText(text: String, userLat: Double?, userLong: Double?, queryId: String? = nil) async -> Result<[SearchPresentation], Error> { do { - let result = try await searchTextRequest(text: text, userLat: userLat, userLong: userLong) + let result = try await searchTextRequest(text: text, userLat: userLat, userLong: userLong, queryId: queryId) var userLocation: CLLocation? = nil if let userLat, let userLong { userLocation = CLLocation(latitude: userLat, longitude: userLong) @@ -48,7 +48,6 @@ struct LocationService: AWSLocationSearchService, LocationServiceable { } } - //@discardableResult func reverseGeocode(position: [Double], userLat: Double?, userLong: Double?) async -> Result<[SearchPresentation], Error> { do { let result = try await reverseGeocodeRequest(position: position) @@ -64,9 +63,8 @@ struct LocationService: AWSLocationSearchService, LocationServiceable { } } - func getPlace(with placeId: String) async throws -> SearchPresentation? { + func getPlace(with placeId: String) async throws -> GetPlaceOutput? { let response = try await getPlaceRequest(with: placeId) - let model = SearchPresentation(model: response!) - return model + return response } } diff --git a/LocationServices/LocationServices/Networking/Services/RoutingServiceable.swift b/LocationServices/LocationServices/Networking/Services/RoutingServiceable.swift index e2c5de60..ea50a361 100644 --- a/LocationServices/LocationServices/Networking/Services/RoutingServiceable.swift +++ b/LocationServices/LocationServices/Networking/Services/RoutingServiceable.swift @@ -38,7 +38,7 @@ struct RoutingAPIService: AWSRoutingServiceProtocol, RoutingServiceable { avoidFerries: avoidFerries, avoidTolls: avoidTolls)! if let route = response.routes?[safe: 0] { - let model = DirectionPresentation(model: route, travelMode: travelMode) + let model = try DirectionPresentation(model: route, travelMode: travelMode) presentationObject[travelMode] = .success(model) } else { diff --git a/LocationServices/LocationServices/Scenes/Explore/Controller/ExploreVC.swift b/LocationServices/LocationServices/Scenes/Explore/Controller/ExploreVC.swift index b2417a0d..19ac4dea 100644 --- a/LocationServices/LocationServices/Scenes/Explore/Controller/ExploreVC.swift +++ b/LocationServices/LocationServices/Scenes/Explore/Controller/ExploreVC.swift @@ -54,6 +54,7 @@ final class ExploreVC: UIViewController { locationManagerSetup() setupView() + exploreView.setupMapView() exploreView.setupTapGesture() } @@ -65,7 +66,6 @@ final class ExploreVC: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - exploreView.setupMapView() showWelcomeScreenIfNeeded() } @@ -434,7 +434,7 @@ extension ExploreVC { } @objc private func refreshMapView(_ notification: Notification) { - exploreView.setupMapView() + exploreView.setupMapView(locateMe: false) } @objc private func logoutAction() { @@ -523,8 +523,10 @@ extension ExploreVC: CLLocationManagerDelegate { } func showAnnotation(model: SearchPresentation, force: Bool) { - guard force || (presentedViewController == nil && viewIfLoaded?.window != nil) else { return } - showPoiCard(cardData: [MapModel(model: model)]) + DispatchQueue.main.async { [self] in + guard force || (presentedViewController == nil && viewIfLoaded?.window != nil) else { return } + showPoiCard(cardData: [MapModel(model: model)]) + } } } diff --git a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/Controller/DirectionVC.swift b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/Controller/DirectionVC.swift index 93f6b104..bc0da8e5 100644 --- a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/Controller/DirectionVC.swift +++ b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/Controller/DirectionVC.swift @@ -294,7 +294,8 @@ final class DirectionVC: UIViewController { locationCity: nil, label: nil, long: secondDestination?.long, - lat: secondDestination?.lat) + lat: secondDestination?.lat, + queryId: nil, queryType: nil) try await calculateGenericRoute(currentModel: currentModel, routeType: routeType, avoidFerries: avoidFerries, @@ -308,23 +309,22 @@ final class DirectionVC: UIViewController { func calculateGenericRoute(currentModel: SearchCellViewModel, routeType: RouteTypes = .car, avoidFerries: Bool = false, avoidTolls: Bool = false) async throws { guard let (departureLocation, destinationLocation) = getRouteLocations(currentModel: currentModel) else { return } - showLoadingIndicator() + guard isDistanceValid(departureLoc: departureLocation, destinationLoc: destinationLocation) else { return } + + showLoadingIndicator() + self.tableView.isHidden = true + if let (data, directionVM) = try await viewModel.calculateRouteWith(destinationPosition: destinationLocation, departurePosition: departureLocation, travelMode: routeType, avoidFerries: avoidFerries, avoidTolls: avoidTolls) { DispatchQueue.main.async { - self.tableView.isHidden = true self.directionView.isHidden = false - let isPreview = self.firstDestination?.placeName != "My Location" self.directionView.setup(model: directionVM, isPreview: isPreview) - self.directionView.showOptionsStackView() - - self.setupSearchTitleDestinations() self.view.endEditing(true) self.sendDirectionsToExploreVC(data: data, @@ -390,12 +390,14 @@ final class DirectionVC: UIViewController { let destinationLoc = CLLocationCoordinate2D(latitude: destinationLat, longitude: destinationLong) guard isDistanceValid(departureLoc: departureLoc, destinationLoc: destinationLoc) else { return } + showLoadingIndicator() + + if let (data, directionVM) = try await viewModel.calculateRouteWith(destinationPosition: destinationLoc, departurePosition: departureLoc, avoidFerries: viewModel.avoidFerries, avoidTolls: viewModel.avoidTolls) { - - self.tableView.isHidden = true - self.directionView.isHidden = false - DispatchQueue.main.async { + self.hideLoadingIndicator() + self.directionView.isHidden = false + self.tableView.isHidden = true self.directionView.showOptionsStackView() } @@ -464,7 +466,8 @@ extension DirectionVC: DirectionViewModelOutputDelegate { locationCity: model.placeCity, label: model.placeName, long: model.placeLong, - lat: model.placeLat) + lat: model.placeLat, + queryId: model.queryId, queryType: model.queryType) let searchTextModel = DirectionTextFieldModel(placeName: currentModel.locationName ?? "", placeAddress: model.placeAddress, lat: currentModel.lat, long: currentModel.long) diff --git a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/Presentation/DirectionPresentation.swift b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/Presentation/DirectionPresentation.swift index 7df8f510..670b6e6c 100644 --- a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/Presentation/DirectionPresentation.swift +++ b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/Presentation/DirectionPresentation.swift @@ -15,7 +15,7 @@ struct DirectionPresentation { let duration: Double var routeLegDetails: [RouteLegDetails]? = nil - init(model: GeoRoutesClientTypes.Route, travelMode: GeoRoutesClientTypes.RouteTravelMode) { + init(model: GeoRoutesClientTypes.Route, travelMode: GeoRoutesClientTypes.RouteTravelMode) throws { self.distance = Double(model.summary?.distance ?? 0) self.duration = Double(model.summary?.duration ?? 0) @@ -27,17 +27,17 @@ struct DirectionPresentation { for leg in legs { if let legDetails = leg.pedestrianLegDetails { var legDetails = RouteLegDetails(model: legDetails) - legDetails.setLineString(leg: leg) + try legDetails.setLineString(leg: leg) routeLegDetails?.append(legDetails) } if let legDetails = leg.vehicleLegDetails { var legDetails = RouteLegDetails(model: legDetails) - legDetails.setLineString(leg: leg) + try legDetails.setLineString(leg: leg) routeLegDetails?.append(legDetails) } if let legDetails = leg.ferryLegDetails { var legDetails = RouteLegDetails(model: legDetails) - legDetails.setLineString(leg: leg) + try legDetails.setLineString(leg: leg) routeLegDetails?.append(legDetails) } } @@ -75,9 +75,9 @@ struct RouteLegDetails { }) ?? [] } - mutating func setLineString(leg: GeoRoutesClientTypes.RouteLeg) { - let geometry = Geometry(type: "LineString", coordinates: leg.geometry?.lineString as? [[Double]]) - let properties = Properties(name: "Crema to Council Cres") + mutating func setLineString(leg: GeoRoutesClientTypes.RouteLeg) throws { + let geometry = Geometry(type: "LineString", coordinates: leg.geometry?.lineString) + let properties = Properties(name: "Polyline") let feature = [Feature(type: "Feature", properties: properties, geometry: geometry)] self.lineString = GeoData(type: "FeatureCollection", features: feature) } diff --git a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/ViewModel/DirectionViewModel.swift b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/ViewModel/DirectionViewModel.swift index e0b6acfe..a97ccf19 100644 --- a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/ViewModel/DirectionViewModel.swift +++ b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/ViewModel/DirectionViewModel.swift @@ -64,10 +64,10 @@ final class DirectionViewModel: DirectionViewModelProtocol { return } - + let mapCenter = UserDefaultsHelper.getObject(value: LocationCoordinate2D.self, key: .mapCenter) if text.isCoordinate() { let requestValue = text.convertTextToCoordinate() - let response = await service.reverseGeocode(position: requestValue, userLat: userLat, userLong: userLong) + let response = await service.reverseGeocode(position: requestValue, userLat: mapCenter != nil ? mapCenter?.latitude : userLat, userLong: mapCenter != nil ? mapCenter?.longitude : userLong) switch response { case .success(let results): self.presentation = results @@ -80,7 +80,7 @@ final class DirectionViewModel: DirectionViewModelProtocol { } } } else { - let response = await service.searchWithSuggest(text: text, userLat: userLat, userLong: userLong) + let response = await service.searchWithSuggest(text: text, userLat: mapCenter != nil ? mapCenter?.latitude : userLat, userLong: mapCenter != nil ? mapCenter?.longitude : userLong) switch response { case .success(let results): self.presentation = results @@ -106,10 +106,10 @@ final class DirectionViewModel: DirectionViewModelProtocol { delegate?.searchResult(mapModel: []) return } - + let mapCenter = UserDefaultsHelper.getObject(value: LocationCoordinate2D.self, key: .mapCenter) if text.isCoordinate() { let requestValue = text.convertTextToCoordinate() - let response = await service.reverseGeocode(position: requestValue, userLat: userLat, userLong: userLong) + let response = await service.reverseGeocode(position: requestValue, userLat: mapCenter != nil ? mapCenter?.latitude : userLat, userLong: mapCenter != nil ? mapCenter?.longitude : userLong) switch response { case .success(let results): self.presentation = results @@ -122,7 +122,7 @@ final class DirectionViewModel: DirectionViewModelProtocol { } } } else { - let result = await service.searchText(text: text, userLat: userLat, userLong: userLong) + let result = await service.searchText(text: text, userLat: mapCenter != nil ? mapCenter?.latitude : userLat, userLong: mapCenter != nil ? mapCenter?.longitude : userLong, queryId: nil) let resultValue = try result.get() self.presentation = resultValue self.addMyLocationItem() @@ -149,14 +149,23 @@ final class DirectionViewModel: DirectionViewModelProtocol { func getSearchCellModel() -> [SearchCellViewModel] { searchCellModel = presentation.map({ - return SearchCellViewModel(searchType: ($0.placeId != nil || $0.placeLat != nil) ? ($0.placeId == "myLocation" ? .mylocation : .location) : .search, + var searchType = SearchType.search + if $0.placeId == "myLocation" { + searchType = .mylocation + } else if $0.suggestType == .place { + searchType = .location + } else { + searchType = .search + } + return SearchCellViewModel(searchType: searchType, placeId: $0.placeId, locationName: $0.name, locationDistance: $0.distance, locationCountry: $0.countryName, locationCity: $0.cityName, label: $0.fullLocationAddress, - long: $0.placeLong, lat: $0.placeLat) + long: $0.placeLong, lat: $0.placeLat, + queryId: $0.queryId, queryType: $0.queryType) }) return searchCellModel @@ -178,7 +187,7 @@ final class DirectionViewModel: DirectionViewModelProtocol { } else if selectedItem.lat != nil { return true } else { - let result = await service.searchText(text: selectedItem.locationName ?? "", userLat: lat, userLong: long) + let result = await service.searchText(text: selectedItem.locationName ?? "", userLat: lat, userLong: long, queryId: selectedItem.queryId) let resultValue = try result.get() self.presentation = [] self.presentation = resultValue @@ -226,11 +235,13 @@ final class DirectionViewModel: DirectionViewModelProtocol { self.avoidTolls = avoidTolls let result = try await routingService.calculateRouteWith(depaturePosition: departurePosition, destinationPosition: destinationPosition, - travelModes: [GeoRoutesClientTypes.RouteTravelMode.car, GeoRoutesClientTypes.RouteTravelMode.pedestrian, GeoRoutesClientTypes.RouteTravelMode.truck], + travelModes: [GeoRoutesClientTypes.RouteTravelMode.car, GeoRoutesClientTypes.RouteTravelMode.pedestrian, + GeoRoutesClientTypes.RouteTravelMode.scooter, + GeoRoutesClientTypes.RouteTravelMode.truck], avoidFerries: avoidFerries, avoidTolls: avoidTolls) self.defaultTravelMode = result - var directionVM: DirectionVM = DirectionVM(carTypeDistane: "", carTypeDuration: "", walkingTypeDuration: "", walkingTypeDistance: "", truckTypeDistance: "", truckTypeDuration: "") + var directionVM: DirectionVM = DirectionVM(carTypeDistane: "", carTypeDuration: "", scooterTypeDuration: "", scooterTypeDistance: "", walkingTypeDuration: "", walkingTypeDistance: "", truckTypeDistance: "", truckTypeDuration: "") result.values.forEach { model in switch model { @@ -239,6 +250,9 @@ final class DirectionViewModel: DirectionViewModelProtocol { case .car: directionVM.carTypeDistane = model.distance.formatToKmString() directionVM.carTypeDuration = model.duration.convertSecondsToMinString() + case .scooter: + directionVM.scooterTypeDistance = model.distance.formatToKmString() + directionVM.scooterTypeDuration = model.duration.convertSecondsToMinString() case .pedestrian: directionVM.walkingTypeDistance = model.distance.formatToKmString() directionVM.walkingTypeDuration = model.duration.convertSecondsToMinString() diff --git a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/Views/Common Views/RouteTypeView.swift b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/Views/Common Views/RouteTypeView.swift index f2313945..c29649db 100644 --- a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/Views/Common Views/RouteTypeView.swift +++ b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/Views/Common Views/RouteTypeView.swift @@ -9,12 +9,14 @@ import UIKit import SnapKit enum RouteTypes { - case pedestrian, car, truck + case pedestrian, scooter, car, truck var title: String { switch self { case .pedestrian: return "Pedestrian" + case .scooter: + return "Scooter" case .car: return "Car" case .truck: @@ -26,6 +28,8 @@ enum RouteTypes { switch self { case .pedestrian: return .navigationWalkingIcon.withRenderingMode(.alwaysTemplate) + case .scooter: + return .navigationScooterIcon.withRenderingMode(.alwaysTemplate) case .car: return .navigationCarIcon.withRenderingMode(.alwaysTemplate) case .truck: @@ -152,7 +156,8 @@ final class RouteTypeView: UIView { let isGoButtonEnabled = !distance.isEmpty && !duration.isEmpty self.goButton.alpha = isGoButtonEnabled ? 1 : 0.3 - + self.goButton.isEnabled = isGoButtonEnabled + self.isUserInteractionEnabled = isGoButtonEnabled let goButtonTitle = isPreview ? StringConstant.preview : StringConstant.go self.goButton.setTitle(goButtonTitle, for: .normal) self.layoutIfNeeded() @@ -186,13 +191,13 @@ final class RouteTypeView: UIView { routeTypeImage.snp.makeConstraints { $0.width.height.equalTo(20) - $0.leading.equalToSuperview().offset(18) + $0.leading.equalToSuperview().offset(10) $0.centerY.equalToSuperview() } leftContainerView.snp.makeConstraints { $0.centerY.equalTo(routeTypeImage.snp.centerY) - $0.leading.equalTo(routeTypeImage.snp.trailing).offset(16) + $0.leading.equalTo(routeTypeImage.snp.trailing).offset(10) } routeTypeTitle.snp.makeConstraints { @@ -219,7 +224,7 @@ final class RouteTypeView: UIView { } goButton.snp.makeConstraints { - $0.trailing.equalToSuperview().offset(-16) + $0.trailing.equalToSuperview().offset(-10) $0.width.equalTo(77) $0.height.equalTo(40) $0.centerY.equalToSuperview() @@ -231,7 +236,7 @@ final class RouteTypeView: UIView { } durationLabel.snp.makeConstraints { - $0.trailing.equalTo(goButton.snp.leading).offset(-24) + $0.trailing.equalTo(goButton.snp.leading).offset(-10) $0.height.equalTo(28) $0.centerY.equalTo(goButton.snp.centerY) $0.leading.equalTo(leftContainerView.snp.trailing).offset(5) diff --git a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/Views/DirectionView.swift b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/Views/DirectionView.swift index dd656c8d..5ea1d6d3 100644 --- a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/Views/DirectionView.swift +++ b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Direction/Views/DirectionView.swift @@ -10,6 +10,8 @@ import UIKit struct DirectionVM { var carTypeDistane: String var carTypeDuration: String + var scooterTypeDuration: String + var scooterTypeDistance: String var walkingTypeDuration: String var walkingTypeDistance: String var truckTypeDistance: String @@ -24,6 +26,7 @@ final class DirectionView: UIView { private var model: DirectionVM! { didSet { carRouteTypeView.setDatas(distance: model.carTypeDistane, duration: model.carTypeDuration, isPreview: isPreview) + scooterRouteTypeView.setDatas(distance: model.scooterTypeDistance, duration: model.scooterTypeDuration, isPreview: isPreview) pedestrianRouteTypeView.setDatas(distance: model.walkingTypeDistance, duration: model.walkingTypeDuration, isPreview: isPreview) truckRouteTypeView.setDatas(distance: model.truckTypeDistance, duration: model.truckTypeDuration, isPreview: isPreview) } @@ -58,6 +61,12 @@ final class DirectionView: UIView { view.backgroundColor = .searchBarBackgroundColor return view }() + private var scooterRouteTypeView: RouteTypeView = RouteTypeView(viewType: .scooter) + private var scooterSeperatorView: UIView = { + let view = UIView() + view.backgroundColor = .searchBarBackgroundColor + return view + }() private var truckRouteTypeView: RouteTypeView = RouteTypeView(viewType: .truck) private var routeTypeStackView: UIStackView = { @@ -161,6 +170,18 @@ final class DirectionView: UIView { } + scooterRouteTypeView.isSelectedHandle = { [weak self] state in + self?.changeSelectedTextFor(scooterType: state) + Task { + try await self?.delegate?.changeRoute(type: .scooter) + } + } + + scooterRouteTypeView.goButtonHandler = { [weak self] in + self?.delegate?.startNavigation(type: .scooter) + + } + truckRouteTypeView.isSelectedHandle = { [weak self] state in self?.changeSelectedTextFor(truckType: state) Task { @@ -199,9 +220,11 @@ final class DirectionView: UIView { private func changeSelectedTextFor(carType: Bool = false, walkingType: Bool = false, + scooterType: Bool = false, truckType: Bool = false) { carRouteTypeView.isDotViewVisible(carType) pedestrianRouteTypeView.isDotViewVisible(walkingType) + scooterRouteTypeView.isDotViewVisible(scooterType) truckRouteTypeView.isDotViewVisible(truckType) } @@ -218,6 +241,7 @@ final class DirectionView: UIView { private func setupViews() { carRouteTypeView.accessibilityIdentifier = ViewsIdentifiers.Routing.carContainer pedestrianRouteTypeView.accessibilityIdentifier = ViewsIdentifiers.Routing.pedestrianContainer + scooterRouteTypeView.accessibilityIdentifier = ViewsIdentifiers.Routing.scooterContainer truckRouteTypeView.accessibilityIdentifier = ViewsIdentifiers.Routing.truckContainer routeTypeStackView.removeArrangedSubViews() @@ -225,6 +249,8 @@ final class DirectionView: UIView { routeTypeStackView.addArrangedSubview(carSeperatorView) routeTypeStackView.addArrangedSubview(pedestrianRouteTypeView) routeTypeStackView.addArrangedSubview(pedestrianSeperatorView) + routeTypeStackView.addArrangedSubview(scooterRouteTypeView) + routeTypeStackView.addArrangedSubview(scooterSeperatorView) routeTypeStackView.addArrangedSubview(truckRouteTypeView) self.addSubview(routeOptions) @@ -260,6 +286,14 @@ final class DirectionView: UIView { $0.height.equalTo(1) } + scooterRouteTypeView.snp.makeConstraints { + $0.height.equalTo(72) + } + + scooterSeperatorView.snp.makeConstraints { + $0.height.equalTo(1) + } + truckRouteTypeView.snp.makeConstraints { $0.height.equalTo(72) } diff --git a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Controller/ExploreMapStyleVC.swift b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Controller/ExploreMapStyleVC.swift index 9fef7715..7d562d55 100644 --- a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Controller/ExploreMapStyleVC.swift +++ b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Controller/ExploreMapStyleVC.swift @@ -13,6 +13,7 @@ final class ExploreMapStyleVC: UIViewController { var headerView: ExploreMapStyleHeaderView = ExploreMapStyleHeaderView() var colorSegment: ColorSegmentControl? = nil var politicalView = PoliticalView() + var languageView = LanguageView() var viewModel: ExploreMapStyleViewModelProtocol! { didSet { @@ -48,11 +49,12 @@ final class ExploreMapStyleVC: UIViewController { let colorNames = [MapStyleColorType.light.colorName, MapStyleColorType.dark.colorName] colorSegment = ColorSegmentControl(items: colorNames) - view.backgroundColor = .searchBarBackgroundColor + view.backgroundColor = .white self.view.addSubview(headerView) self.view.addSubview(tableView) self.view.addSubview(colorSegment!) self.view.addSubview(politicalView) + self.view.addSubview(languageView) headerView.snp.makeConstraints { $0.top.equalTo(self.view.safeAreaLayoutGuide) @@ -86,7 +88,14 @@ final class ExploreMapStyleVC: UIViewController { $0.width.equalToSuperview() } + languageView.snp.makeConstraints { + $0.top.equalTo(politicalView.snp.bottom).offset(50) + $0.centerX.equalToSuperview() + $0.width.equalToSuperview() + } + politicalView.viewController = self + languageView.viewController = self } } diff --git a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/Cell/ExploreMapStyleCell.swift b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/Cell/ExploreMapStyleCell.swift index 680c8a09..8f7bd1db 100644 --- a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/Cell/ExploreMapStyleCell.swift +++ b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/Cell/ExploreMapStyleCell.swift @@ -21,7 +21,6 @@ final class ExploreMapStyleCell: UITableViewCell { private var containerView: UIView = { let view = UIView() - view.backgroundColor = .white view.layer.cornerRadius = 10 view.isUserInteractionEnabled = true return view @@ -53,8 +52,6 @@ final class ExploreMapStyleCell: UITableViewCell { override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) self.selectionStyle = .none - self.backgroundColor = .clear - self.backgroundColor = .clear setupCollectionView() setupViews() } diff --git a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/Cell/LanguageViewCell.swift b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/Cell/LanguageViewCell.swift new file mode 100644 index 00000000..1dc2a9dd --- /dev/null +++ b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/Cell/LanguageViewCell.swift @@ -0,0 +1,51 @@ +import UIKit + +class LanguageViewCell: UITableViewCell { + private let containerView: UIView = UIView() + private let contentCellView: UIView = UIView() + + private var itemTitle: UILabel = { + var label = UILabel() + label.font = .amazonFont(type: .regular, size: 16) + label.textColor = .mapDarkBlackColor + label.textAlignment = .left + label.text = "Language" + return label + }() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setupViews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupViews() { + self.addSubview(containerView) + containerView.addSubview(contentCellView) + contentCellView.addSubview(itemTitle) + + containerView.snp.makeConstraints { + $0.top.leading.trailing.bottom.equalToSuperview() + } + + contentCellView.snp.makeConstraints { + $0.top.equalToSuperview().offset(10) + $0.leading.equalToSuperview().offset(2) + $0.trailing.equalToSuperview().offset(-20) + $0.bottom.equalToSuperview().offset(-10) + } + + itemTitle.snp.makeConstraints { + $0.leading.equalToSuperview().offset(5) + $0.top.equalToSuperview() + $0.trailing.lessThanOrEqualToSuperview().offset(-12) + } + } + + func configure(with languageSwitcherData: LanguageSwitcherData) { + itemTitle.text = languageSwitcherData.label + } +} diff --git a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/Cell/PoliticalViewCell.swift b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/Cell/PoliticalViewCell.swift index fa3a0210..6dc879ca 100644 --- a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/Cell/PoliticalViewCell.swift +++ b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/Cell/PoliticalViewCell.swift @@ -74,9 +74,15 @@ class PoliticalViewCell: UITableViewCell { func configure(with politicalView: PoliticalViewType) { let countryFlag = flag(country: politicalView.flagCode) + if politicalView.flagCode.isEmpty { + itemIcon.isHidden = true + } + else { + itemIcon.isHidden = false + } itemTitle.text = politicalView.fullName itemIcon.text = countryFlag - itemIcon.font = UIFont.systemFont(ofSize: 24) // Adjust flag size + itemIcon.font = UIFont.systemFont(ofSize: 24) itemSubtitle.text = politicalView.politicalDescription } diff --git a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/LanguageView.swift b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/LanguageView.swift new file mode 100644 index 00000000..d4e972be --- /dev/null +++ b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/LanguageView.swift @@ -0,0 +1,130 @@ +// +// LanguageView.swift +// LocationServices +// +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: MIT-0 + +import UIKit + +final class LanguageView: UIButton { + private var itemIcon: UIImageView = { + let image = UIImage(systemName: "captions.bubble.fill") + let iv = UIImageView(image: image) + iv.contentMode = .scaleAspectFit + iv.tintColor = .mapStyleTintColor + return iv + }() + + private var itemTitle: UILabel = { + var label = UILabel() + label.font = .amazonFont(type: .medium, size: 18) + label.textColor = .mapDarkBlackColor + label.textAlignment = .left + label.text = "Map Language" + return label + }() + + private var itemSubtitle: UILabel = { + var label = UILabel() + label.font = .amazonFont(type: .regular, size: 13) + label.textColor = .gray + label.textAlignment = .left + label.text = "" + label.accessibilityIdentifier = ViewsIdentifiers.General.languageViewSubtitle + return label + }() + + private var arrowIcon: UIImageView = { + let image = UIImage(systemName: "chevron.right") + let iv = UIImageView(image: image) + iv.contentMode = .scaleAspectFill + iv.tintColor = .searchBarTintColor + return iv + }() + + private var textStackView: UIStackView = { + let stackView = UIStackView() + stackView.alignment = .leading + stackView.axis = .vertical + stackView.distribution = .equalSpacing + return stackView + }() + + private var containerView: UIView = UIView() + public var viewController: UIViewController? + + override init(frame: CGRect) { + super.init(frame: frame) + setupViews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupViews() { + self.accessibilityIdentifier = ViewsIdentifiers.General.languageViewButton + textStackView.removeArrangedSubViews() + textStackView.addArrangedSubview(itemTitle) + textStackView.addArrangedSubview(itemSubtitle) + + self.addSubview(containerView) + containerView.addSubview(itemIcon) + containerView.addSubview(arrowIcon) + containerView.addSubview(textStackView) + + containerView.snp.makeConstraints { + $0.top.leading.trailing.bottom.equalToSuperview() + } + + itemIcon.snp.makeConstraints { + $0.height.width.equalTo(32) + $0.leading.equalToSuperview().offset(18) + $0.centerY.equalToSuperview() + } + + arrowIcon.snp.makeConstraints { + $0.height.width.equalTo(14) + $0.trailing.equalToSuperview().offset(-25) + $0.centerY.equalToSuperview() + } + + textStackView.snp.makeConstraints { + $0.height.equalTo(46) + $0.leading.equalTo(itemIcon.snp.trailing).offset(24) + $0.trailing.equalTo(arrowIcon.snp.leading) + $0.centerY.equalToSuperview() + } + + self.isUserInteractionEnabled = true + let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture)) + self.addGestureRecognizer(tapGestureRecognizer) + + setLanguage() + } + + @objc private func handleTapGesture() { + let languageVC = LanguageViewController() + languageVC.modalPresentationStyle = .formSheet + languageVC.onDismiss = { + self.setLanguage() + } + viewController?.present(languageVC, animated: true) + } + + public func setLanguage() { + var language = Locale.currentLanguageIdentifier() + var selectedIndex = languageSwitcherData.firstIndex(where: { type in + if type.value == language { + return true + } + return false + }) + if selectedIndex != nil { + language = languageSwitcherData[selectedIndex!].label + } + itemSubtitle.text = language + itemSubtitle.textColor = .mapStyleTintColor + } +} diff --git a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/LanguageViewController.swift b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/LanguageViewController.swift new file mode 100644 index 00000000..9bf084a7 --- /dev/null +++ b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/LanguageViewController.swift @@ -0,0 +1,154 @@ +// +// LanguageViewController.swift +// LocationServices +// +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: MIT-0 + +import UIKit + +class LanguageViewController: UIViewController, UISearchBarDelegate, UITableViewDelegate, UITableViewDataSource { + var selectedIndexPath: IndexPath? + var tableView: UITableView! + private var isSearching: Bool = false + + private var headerView: UIView = { + let view = UIView() + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + private var titleLabel: UILabel = { + let label = UILabel() + label.text = "Select Language" + label.font = .boldSystemFont(ofSize: 18) + label.textAlignment = .center + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + private lazy var closeButton: UIButton = { + let button = UIButton(type: .detailDisclosure) + button.accessibilityIdentifier = ViewsIdentifiers.General.languageViewCloseButton + button.setImage(.closeIcon, for: .normal) + button.tintColor = .closeButtonTintColor + button.backgroundColor = .closeButtonBackgroundColor + button.isUserInteractionEnabled = true + button.layer.cornerRadius = 15 + button.addTarget(self, action: #selector(languageViewDismiss), for: .touchUpInside) + return button + }() + + var onDismiss: (() -> Void)? + + @objc private func languageViewDismiss() { + self.dismiss(animated: true) + onDismiss?() + } + + @objc private func clearLanguage() { + selectedIndexPath = nil + UserDefaultsHelper.removeObject(for: .language) + tableView.reloadData() + NotificationCenter.default.post(name: Notification.refreshMapView, object: nil, userInfo: nil) + } + + override func viewDidLoad() { + super.viewDidLoad() + + view.backgroundColor = .politicalListViewBackgroundColor + + headerView.addSubview(titleLabel) + headerView.addSubview(closeButton) + view.addSubview(headerView) + + tableView = UITableView(frame: view.bounds) + tableView.accessibilityIdentifier = ViewsIdentifiers.General.languageViewTable + tableView.dataSource = self + tableView.delegate = self + tableView.register(LanguageViewCell.self, forCellReuseIdentifier: ViewsIdentifiers.General.languageViewCell) + view.addSubview(tableView) + + headerView.snp.makeConstraints { + $0.top.leading.equalToSuperview().offset(10) + $0.trailing.equalToSuperview().offset(-10) + $0.height.equalTo(50) + } + + titleLabel.snp.makeConstraints { + $0.top.leading.equalToSuperview() + $0.centerY.equalToSuperview() + } + + closeButton.snp.makeConstraints { + $0.top.equalToSuperview().offset(14) + $0.trailing.equalToSuperview().offset(-11) + $0.height.width.equalTo(30) + } + + tableView.snp.makeConstraints { + $0.top.equalTo(headerView.snp.bottom).offset(10) + $0.leading.equalToSuperview().offset(10) + $0.trailing.equalToSuperview().offset(-10) + $0.bottom.equalToSuperview().offset(-40) + } + + + tableView.layer.cornerRadius = 10 + tableView.layer.masksToBounds = true + + + let language = Locale.currentLanguageIdentifier() + var selectedIndex = languageSwitcherData.firstIndex(where: { type in + if type.value == language { + return true + } + return false + }) + if selectedIndex == nil { + selectedIndex = 0 + } + selectedIndexPath = selectedIndex != nil ? IndexPath(row: selectedIndex!, section: 0) : nil + tableView.reloadData() + } + + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return 50 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return languageSwitcherData.count + } + + private var checkedIcon: UIImageView = { + let image = UIImage(systemName: "checkmark") + let iv = UIImageView(image: image) + iv.contentMode = .scaleAspectFill + iv.tintColor = .mapStyleTintColor + return iv + }() + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let cell = tableView.dequeueReusableCell(withIdentifier: ViewsIdentifiers.General.languageViewCell, for: indexPath) as? LanguageViewCell else { + return UITableViewCell() + } + let language = languageSwitcherData[indexPath.row] + cell.configure(with: language) + + if let selectedIndexPath = selectedIndexPath, selectedIndexPath == indexPath { + cell.accessoryView = checkedIcon + } else { + cell.accessoryView = nil + } + + return cell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + selectedIndexPath = indexPath + UserDefaultsHelper.saveObject(value: languageSwitcherData[indexPath.row], key: .language) + tableView.reloadData() + NotificationCenter.default.post(name: Notification.refreshMapView, object: nil, userInfo: nil) + } +} diff --git a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/PoliticalViewController.swift b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/PoliticalViewController.swift index d732ca69..eab0dab8 100644 --- a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/PoliticalViewController.swift +++ b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Explore Map Style/Views/PoliticalViewController.swift @@ -41,15 +41,6 @@ class PoliticalViewController: UIViewController, UISearchBarDelegate, UITableVie return button }() - private lazy var clearButton: UIButton = { - let button = UIButton(type: .system) - button.setTitle("Clear Selection", for: .normal) - button.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) - button.addTarget(self, action: #selector(clearPoliticalView), for: .touchUpInside) - button.translatesAutoresizingMaskIntoConstraints = false - return button - }() - private var searchBar: UISearchBar = { let searchBar = UISearchBar() searchBar.placeholder = "Search" @@ -87,8 +78,6 @@ class PoliticalViewController: UIViewController, UISearchBarDelegate, UITableVie searchBar.delegate = self view.addSubview(searchBar) - view.addSubview(clearButton) - tableView = UITableView(frame: view.bounds) tableView.accessibilityIdentifier = ViewsIdentifiers.General.politicalViewTable tableView.dataSource = self @@ -120,13 +109,8 @@ class PoliticalViewController: UIViewController, UISearchBarDelegate, UITableVie $0.height.equalTo(60) } - clearButton.snp.makeConstraints { - $0.top.equalTo(searchBar.snp.bottom) - $0.trailing.equalToSuperview().offset(-10) - } - tableView.snp.makeConstraints { - $0.top.equalTo(clearButton.snp.bottom).offset(10) + $0.top.equalTo(searchBar.snp.bottom).offset(10) $0.leading.equalToSuperview().offset(10) $0.trailing.equalToSuperview().offset(-10) $0.bottom.equalToSuperview().offset(-40) @@ -142,12 +126,15 @@ class PoliticalViewController: UIViewController, UISearchBarDelegate, UITableVie filteredPoliticalViews = PoliticalViewTypes let politicalViewType = UserDefaultsHelper.getObject(value: PoliticalViewType.self, key: .politicalView) - let selectedIndex = filteredPoliticalViews.firstIndex(where: { type in + var selectedIndex = filteredPoliticalViews.firstIndex(where: { type in if type.countryCode == politicalViewType?.countryCode { return true } return false }) + if selectedIndex == nil { + selectedIndex = 0 + } selectedIndexPath = selectedIndex != nil ? IndexPath(row: selectedIndex!, section: 0) : nil tableView.reloadData() } @@ -191,7 +178,12 @@ class PoliticalViewController: UIViewController, UISearchBarDelegate, UITableVie func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) selectedIndexPath = indexPath - UserDefaultsHelper.saveObject(value: filteredPoliticalViews[indexPath.row], key: .politicalView) + if selectedIndexPath?.row == 0 { + UserDefaultsHelper.removeObject(for: .politicalView) + } + else { + UserDefaultsHelper.saveObject(value: filteredPoliticalViews[indexPath.row], key: .politicalView) + } tableView.reloadData() NotificationCenter.default.post(name: Notification.refreshMapView, object: nil, userInfo: nil) } diff --git a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/POICard/Contracts/POICardVCContracts.swift b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/POICard/Contracts/POICardVCContracts.swift index 184acb52..70b9f0c7 100644 --- a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/POICard/Contracts/POICardVCContracts.swift +++ b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/POICard/Contracts/POICardVCContracts.swift @@ -18,5 +18,6 @@ protocol POICardViewModelOutputDelegate: AnyObject, AlertPresentable { func dismissPoiView() func showDirectionView(seconDestination: MapModel) func updateSizeClass(_ sizeClass: POICardVC.DetentsSizeClass) + func setPOIHeight(_ height: CGFloat) } diff --git a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/POICard/Controller/POICardVC.swift b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/POICard/Controller/POICardVC.swift index eff06223..cfdc417c 100755 --- a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/POICard/Controller/POICardVC.swift +++ b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/POICard/Controller/POICardVC.swift @@ -172,6 +172,11 @@ extension POICardVC: POICardViewModelOutputDelegate { sheetPresentationController?.detents = [smallDetent] sheetPresentationController?.largestUndimmedDetentIdentifier = smallId } + + func setPOIHeight(_ height: CGFloat) + { + self.setBottomSheetHeight(to: height) + } } extension POICardVC: CLLocationManagerDelegate { diff --git a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Search/Presentation/SearchPresentation.swift b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Search/Presentation/SearchPresentation.swift index e6240928..8341b85a 100644 --- a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Search/Presentation/SearchPresentation.swift +++ b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Search/Presentation/SearchPresentation.swift @@ -20,6 +20,11 @@ struct SearchPresentation { let placeLong: Double? let name: String? let placeLabel: String? + var place: GetPlaceOutput? = nil + let placeType: GeoPlacesClientTypes.PlaceType? + let queryType: GeoPlacesClientTypes.QueryType? + let suggestType: GeoPlacesClientTypes.SuggestResultItemType? + let queryId: String? init( placeId: String?, fullLocationAddress: String?, @@ -39,6 +44,10 @@ struct SearchPresentation { self.placeLong = placeLong self.name = name self.placeLabel = fullLocationAddress + self.placeType = .none + self.queryType = .none + self.suggestType = .none + self.queryId = nil } init(placeId: String, model: GetPlaceOutput) { @@ -61,6 +70,10 @@ struct SearchPresentation { } self.cityName = model.address?.district self.placeLabel = model.address?.label + self.placeType = model.placeType + self.suggestType = .none + self.queryType = .none + self.queryId = nil } init(model: GeoPlacesClientTypes.SearchTextResultItem, placeLat: Double? = nil, placeLong: Double? = nil, userLocation: CLLocation? = nil) { @@ -86,6 +99,10 @@ struct SearchPresentation { self.distance = nil } self.placeLabel = model.title + self.placeType = model.placeType + self.queryType = .none + self.suggestType = .place + self.queryId = nil } init(model: GeoPlacesClientTypes.SearchNearbyResultItem, placeLat: Double? = nil, placeLong: Double? = nil, userLocation: CLLocation? = nil) { @@ -111,6 +128,10 @@ struct SearchPresentation { self.distance = nil } self.placeLabel = model.title + self.placeType = model.placeType + self.queryType = .none + self.suggestType = .none + self.queryId = nil } init(model: GeoPlacesClientTypes.ReverseGeocodeResultItem, userLocation: CLLocation? = nil) { @@ -135,6 +156,10 @@ struct SearchPresentation { self.distance = nil } self.placeLabel = model.title + self.placeType = model.placeType + self.queryType = .none + self.suggestType = .none + self.queryId = nil } init(model: GetPlaceOutput) { @@ -157,6 +182,11 @@ struct SearchPresentation { self.distance = nil self.cityName = model.address?.district self.placeLabel = model.title + self.placeType = model.placeType + self.queryType = .none + self.suggestType = .none + self.queryId = nil + self.place = model } init(model: GeoPlacesClientTypes.SuggestResultItem, userLocation: CLLocation? = nil) { @@ -179,6 +209,10 @@ struct SearchPresentation { } self.cityName = model.place?.address?.district self.placeLabel = model.title + self.placeType = model.place?.placeType + self.queryType = model.query?.queryType + self.suggestType = model.suggestResultItemType + self.queryId = model.query?.queryId } init(model: GeoPlacesClientTypes.SearchTextResultItem, userLocation: CLLocation?) { @@ -198,5 +232,9 @@ struct SearchPresentation { self.cityName = model.address?.district self.placeLabel = model.title + self.placeType = model.placeType + self.queryType = .none + self.suggestType = .place + self.queryId = nil } } diff --git a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Search/ViewModel/SearchViewModel.swift b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Search/ViewModel/SearchViewModel.swift index f25b5786..2dd918ba 100644 --- a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Search/ViewModel/SearchViewModel.swift +++ b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Search/ViewModel/SearchViewModel.swift @@ -6,6 +6,7 @@ // SPDX-License-Identifier: MIT-0 import Foundation +import CoreLocation final class SearchViewModel: SearchViewModelProcotol { @@ -28,10 +29,10 @@ final class SearchViewModel: SearchViewModelProcotol { self.delegate?.searchResult(mapModel: [], shouldDismiss: false, showOnMap: false) return } - + let mapCenter = UserDefaultsHelper.getObject(value: LocationCoordinate2D.self, key: .mapCenter) if text.isCoordinate() { let requestValue = text.convertTextToCoordinate() - let response = await service.reverseGeocode(position: requestValue, userLat: userLat, userLong: userLong) + let response = await service.reverseGeocode(position: requestValue, userLat: mapCenter != nil ? mapCenter?.latitude : userLat, userLong: mapCenter != nil ? mapCenter?.longitude : userLong) switch response { case .success(let results): self.presentation = results @@ -44,7 +45,7 @@ final class SearchViewModel: SearchViewModelProcotol { } } } else { - let response = await service.searchWithSuggest(text: text, userLat: userLat, userLong: userLong) + let response = await service.searchWithSuggest(text: text, userLat: mapCenter != nil ? mapCenter?.latitude : userLat, userLong: mapCenter != nil ? mapCenter?.longitude : userLong) switch response { case .success(let results): self.presentation = results @@ -65,10 +66,10 @@ final class SearchViewModel: SearchViewModelProcotol { self.delegate?.searchResult(mapModel: [], shouldDismiss: false, showOnMap: false) return } - + let mapCenter = UserDefaultsHelper.getObject(value: LocationCoordinate2D.self, key: .mapCenter) if text.isCoordinate() { let requestValue = text.convertTextToCoordinate() - let response = await service.reverseGeocode(position: requestValue, userLat: userLat, userLong: userLong) + let response = await service.reverseGeocode(position: requestValue, userLat: mapCenter != nil ? mapCenter?.latitude : userLat, userLong: mapCenter != nil ? mapCenter?.longitude : userLong) switch response { case .success(let results): self.presentation = results @@ -79,7 +80,7 @@ final class SearchViewModel: SearchViewModelProcotol { self.delegate?.showAlert(model) } } else { - let result = await service.searchText(text: text, userLat: userLat, userLong: userLong) + let result = await service.searchText(text: text, userLat: mapCenter != nil ? mapCenter?.latitude : userLat, userLong: mapCenter != nil ? mapCenter?.longitude : userLong, queryId: nil) let resultValue = try result.get() self.presentation = resultValue let model = resultValue.map(MapModel.init) @@ -93,14 +94,23 @@ final class SearchViewModel: SearchViewModelProcotol { func getSearchCellModel() -> [SearchCellViewModel] { searchCellModel = presentation.map({ - return SearchCellViewModel(searchType: ($0.placeId != nil || $0.placeLat != nil) ? .location : .search, + var searchType = SearchType.search + if $0.placeId == "myLocation" { + searchType = .mylocation + } else if $0.suggestType == .place { + searchType = .location + } else { + searchType = .search + } + return SearchCellViewModel(searchType: searchType, placeId: $0.placeId, locationName: $0.name, locationDistance: $0.distance, locationCountry: $0.countryName, locationCity: $0.cityName, label: $0.fullLocationAddress, - long: $0.placeLong, lat: $0.placeLat) + long: $0.placeLong, lat: $0.placeLat, + queryId: $0.queryId, queryType: $0.queryType) }) return searchCellModel @@ -112,7 +122,8 @@ final class SearchViewModel: SearchViewModelProcotol { Task { let result = try await service.getPlace(with: id) if let result = result { - let mapModel = MapModel(model: result) + let model = SearchPresentation(model: result) + let mapModel = MapModel(model: model) self.delegate?.selectedPlaceResult(mapModel: mapModel) } return true @@ -124,7 +135,8 @@ final class SearchViewModel: SearchViewModelProcotol { return true } else { Task { - let result = await service.searchText(text: selectedItem.locationName ?? "", userLat: lat, userLong: long) + let mapCenter = UserDefaultsHelper.getObject(value: LocationCoordinate2D.self, key: .mapCenter) + let result = await service.searchText(text: selectedItem.locationName ?? "", userLat: mapCenter != nil ? mapCenter?.latitude : lat, userLong: mapCenter != nil ? mapCenter?.longitude : long, queryId: selectedItem.queryId) let resultValue = try result.get() self.presentation = [] self.presentation = resultValue diff --git a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Search/Views/ViewModels/SearchCellViewModel.swift b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Search/Views/ViewModels/SearchCellViewModel.swift index 5af87a1c..ca63d247 100755 --- a/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Search/Views/ViewModels/SearchCellViewModel.swift +++ b/LocationServices/LocationServices/Scenes/Explore/Sub-Scenes/Search/Views/ViewModels/SearchCellViewModel.swift @@ -6,9 +6,10 @@ // SPDX-License-Identifier: MIT-0 import Foundation +import AWSGeoPlaces enum SearchType { - case location, search,mylocation + case location, search, mylocation } struct SearchCellViewModel { @@ -21,6 +22,8 @@ struct SearchCellViewModel { let label: String? let long: Double? let lat: Double? + let queryId: String? + let queryType: GeoPlacesClientTypes.QueryType? init(model: SearchPresentation) { self.placeId = model.placeId @@ -34,11 +37,13 @@ struct SearchCellViewModel { if placeId == "myLocation" { self.searchType = .mylocation - } else if placeId != nil { + } else if model.suggestType == .place { self.searchType = .location } else { self.searchType = .search } + self.queryType = model.queryType + self.queryId = model.queryId } init(searchType: SearchType, @@ -49,7 +54,9 @@ struct SearchCellViewModel { locationCity: String?, label: String?, long: Double?, - lat: Double?) { + lat: Double?, + queryId: String?, + queryType: GeoPlacesClientTypes.QueryType?) { self.searchType = searchType self.placeId = placeId self.locationName = locationName @@ -59,5 +66,7 @@ struct SearchCellViewModel { self.label = label self.long = long self.lat = lat + self.queryType = queryType + self.queryId = queryId } } diff --git a/LocationServices/LocationServices/Scenes/Explore/ViewModel/ExploreViewModel.swift b/LocationServices/LocationServices/Scenes/Explore/ViewModel/ExploreViewModel.swift index b1af9218..d28b8919 100644 --- a/LocationServices/LocationServices/Scenes/Explore/ViewModel/ExploreViewModel.swift +++ b/LocationServices/LocationServices/Scenes/Explore/ViewModel/ExploreViewModel.swift @@ -89,18 +89,22 @@ final class ExploreViewModel: ExploreViewModelProtocol { } func loadPlace(for coordinates: CLLocationCoordinate2D, userLocation: CLLocationCoordinate2D?) async { - let result = await locationService.reverseGeocode(position: [coordinates.longitude, coordinates.latitude], userLat: userLocation?.latitude, userLong: userLocation?.longitude) - DispatchQueue.main.async { - do { - if let model = try result.get().first { - self.delegate?.showAnnotation(model: model, force: false) - } + var biasLocation = userLocation + if let mapCenter = UserDefaultsHelper.getObject(value: LocationCoordinate2D.self, key: .mapCenter) { + biasLocation = CLLocationCoordinate2D(latitude: mapCenter.latitude, longitude: mapCenter.longitude) + } + let result = await locationService.reverseGeocode(position: [coordinates.longitude, coordinates.latitude], userLat: biasLocation?.latitude, userLong: biasLocation?.longitude) + do { + if var model = try result.get().first, let placeId = model.placeId, + let place = try await locationService.getPlace(with: placeId) { + model.place = place + self.delegate?.showAnnotation(model: model, force: false) } - catch { - let model = AlertModel(title: StringConstant.error, message: error.localizedDescription, cancelButton: nil) - DispatchQueue.main.async { - self.delegate?.showAlert(model) - } + } + catch { + let model = AlertModel(title: StringConstant.error, message: error.localizedDescription, cancelButton: nil) + DispatchQueue.main.async { + self.delegate?.showAlert(model) } } } diff --git a/LocationServices/LocationServices/Scenes/Explore/Views/ExploreView.swift b/LocationServices/LocationServices/Scenes/Explore/Views/ExploreView.swift index fcda442f..c4307ad6 100644 --- a/LocationServices/LocationServices/Scenes/Explore/Views/ExploreView.swift +++ b/LocationServices/LocationServices/Scenes/Explore/Views/ExploreView.swift @@ -34,8 +34,8 @@ private enum Constants { static let mapLayerBottomOffset: CGFloat = 16 static let bottomStackViewOffset: CGFloat = 16 - static let topStackViewOffsetiPhone: CGFloat = 16 - static let topStackViewOffsetiPad: CGFloat = 0 + static let topStackViewOffsetiPhone: CGFloat = 50 + static let topStackViewOffsetiPad: CGFloat = 50 } enum MapMode { @@ -74,6 +74,7 @@ final class ExploreView: UIView, NavigationMapProtocol { mapView.tintColor = .lsPrimary mapView.compassView.isHidden = true mapView.zoomLevel = 12 + mapView.minimumZoomLevel = 2 mapView.logoView.isHidden = true mapView.attributionButton.isHidden = true mapView.showsUserHeadingIndicator = false @@ -321,7 +322,7 @@ final class ExploreView: UIView, NavigationMapProtocol { switch routeType { case .pedestrian: isDashedLine = true - case .car, .truck: + case .car, .truck, .scooter: isDashedLine = false } self.createAnnotationsForDirection(departureCoordinates: departureLocation, destinationCoordinates: destinationLocation) @@ -434,11 +435,13 @@ final class ExploreView: UIView, NavigationMapProtocol { } var mapLoaded = false - func setupMapView() { + func setupMapView(locateMe: Bool = true) { DispatchQueue.main.async { [self] in if !mapLoaded { mapView.styleURL = DefaultMapStyles.getMapStyleUrl() - locateMeAction(force: true) + if locateMe { + locateMeAction(force: true) + } mapView.showsUserLocation = true mapView.accessibilityIdentifier = ViewsIdentifiers.General.mapRendering amazonMapLogo.tintColor = GeneralHelper.getAmazonMapLogo() @@ -817,7 +820,7 @@ private extension ExploreView { } topStackView.snp.makeConstraints { - $0.top.equalTo(self.safeAreaLayoutGuide).offset( + $0.top.equalToSuperview().offset( isiPad ? Constants.topStackViewOffsetiPad : Constants.topStackViewOffsetiPhone ) $0.trailing.equalToSuperview().offset(-Constants.defaultHorizontalOffset) @@ -869,28 +872,9 @@ private extension ExploreView { } extension ExploreView: MLNMapViewDelegate { - - - // in the difference of standard approach if we are in live navigation mode we always return to - // current location and zoom mode. + func mapView(_ mapView: MLNMapView, regionDidChangeWith reason: MLNCameraChangeReason, animated: Bool) { - //disabling auto focus on user location while in navigation mode to allow user to view map freely -// switch reason { -// case .gesturePan, .gesturePinch, .gestureRotate, .gestureZoomIn, .gestureZoomOut, .gestureTilt: -// -// if mapMode == .turnByTurnNavigation { -// -// return -// if let userCoordinates = mapView.userLocation?.coordinate, -// CLLocationCoordinate2DIsValid(userCoordinates) { -// mapView.setCenter(userCoordinates, zoomLevel: Constants.navigationMapZoonValue, direction: mapView.direction, animated: true) { [weak self] in -// self?.mapView.userTrackingMode = .followWithCourse -// } -// } -// } -// default: -// break -// } + UserDefaultsHelper.saveObject(value: LocationCoordinate2D(latitude: mapView.centerCoordinate.latitude, longitude: mapView.centerCoordinate.longitude), key: .mapCenter) } func mapView(_ mapView: MLNMapView, didSelect annotation: MLNAnnotation) { @@ -966,6 +950,7 @@ extension ExploreView: MLNMapViewDelegate { self?.updateMapHelperConstraints() self?.mapView.accessibilityIdentifier = ViewsIdentifiers.General.mapRendered self?.mapLoaded = true + } } else { debounceForMapRendering.debounce {} @@ -975,11 +960,19 @@ extension ExploreView: MLNMapViewDelegate { func mapViewWillStartRenderingFrame(_ mapView: MLNMapView) { mapView.accessibilityIdentifier = ViewsIdentifiers.General.mapRendering + + } + + func mapView(_ mapView: MLNMapView, didFinishLoading style: MLNStyle) { + GeneralHelper.setMapLanguage(mapView: mapView, style: style) } //frame callback called multiple times even before all map layers are rendered. The fullRendered propery also isn't reliable as it sends true state before map fully rendered. Based on this debounce manager is used here to overcome these issues. func mapViewDidFinishRenderingFrame(_ mapView: MLNMapView, fullyRendered: Bool) { if fullyRendered { + if let style = mapView.style { + GeneralHelper.setMapLanguage(mapView: mapView, style: style) + } debounceForMapRendering.debounce { [weak self] in self?.updateMapHelperConstraints() self?.mapView.accessibilityIdentifier = ViewsIdentifiers.General.mapRendered diff --git a/LocationServices/LocationServices/Scenes/Geofence/SubViews/AddGeofence/ViewModel/AddGeofenceViewModel.swift b/LocationServices/LocationServices/Scenes/Geofence/SubViews/AddGeofence/ViewModel/AddGeofenceViewModel.swift index 377c5a9b..6b20501b 100644 --- a/LocationServices/LocationServices/Scenes/Geofence/SubViews/AddGeofence/ViewModel/AddGeofenceViewModel.swift +++ b/LocationServices/LocationServices/Scenes/Geofence/SubViews/AddGeofence/ViewModel/AddGeofenceViewModel.swift @@ -83,10 +83,10 @@ final class AddGeofenceViewModel: AddGeofenceViewModelProcotol { self.delegate?.searchResult(mapModel: []) return } - + let mapCenter = UserDefaultsHelper.getObject(value: LocationCoordinate2D.self, key: .mapCenter) if text.isCoordinate() { let requestValue = text.convertTextToCoordinate() - let response = await searchService.reverseGeocode(position: requestValue, userLat: userLat, userLong: userLong) + let response = await searchService.reverseGeocode(position: requestValue, userLat: mapCenter != nil ? mapCenter?.latitude : userLat, userLong: mapCenter != nil ? mapCenter?.longitude : userLong) switch response { case .success(let results): self.presentation = results @@ -97,7 +97,7 @@ final class AddGeofenceViewModel: AddGeofenceViewModelProcotol { self.delegate?.showAlert(model) } } else { - let result = await searchService.searchWithSuggest(text: text, userLat: userLat, userLong: userLong) + let result = await searchService.searchWithSuggest(text: text, userLat: mapCenter != nil ? mapCenter?.latitude : userLat, userLong: mapCenter != nil ? mapCenter?.longitude : userLong) let resultValue = try result.get() self.presentation = resultValue let model = resultValue.map(MapModel.init) @@ -110,10 +110,10 @@ final class AddGeofenceViewModel: AddGeofenceViewModelProcotol { self.delegate?.searchResult(mapModel: []) return } - + let mapCenter = UserDefaultsHelper.getObject(value: LocationCoordinate2D.self, key: .mapCenter) if text.isCoordinate() { let requestValue = text.convertTextToCoordinate() - let response = await searchService.reverseGeocode(position: requestValue, userLat: userLat, userLong: userLong) + let response = await searchService.reverseGeocode(position: requestValue, userLat: mapCenter != nil ? mapCenter?.latitude : userLat, userLong: mapCenter != nil ? mapCenter?.longitude : userLong) switch response { case .success(let results): self.presentation = results @@ -124,7 +124,7 @@ final class AddGeofenceViewModel: AddGeofenceViewModelProcotol { self.delegate?.showAlert(model) } } else { - let result = await searchService.searchText(text: text, userLat: userLat, userLong: userLong) + let result = await searchService.searchText(text: text, userLat: mapCenter != nil ? mapCenter?.latitude : userLat, userLong: mapCenter != nil ? mapCenter?.longitude : userLong, queryId: nil) let resultValue = try result.get() self.presentation = resultValue let model = resultValue.map(MapModel.init) @@ -138,14 +138,24 @@ final class AddGeofenceViewModel: AddGeofenceViewModelProcotol { func getSearchCellModel() -> [SearchCellViewModel] { searchCellModel = presentation.map({ - SearchCellViewModel(searchType: $0.placeId != nil ? .location : .search, + var searchType = SearchType.search + if $0.placeId == "myLocation" { + searchType = .mylocation + } else if $0.suggestType == .place { + searchType = .location + } else { + searchType = .search + } + //$0.placeId != nil ? .location : .search + return SearchCellViewModel(searchType: searchType, placeId: $0.placeId, locationName: $0.name, locationDistance: $0.distance, locationCountry: $0.countryName, locationCity: $0.cityName, label: $0.fullLocationAddress, - long: $0.placeLong, lat: $0.placeLat) + long: $0.placeLong, lat: $0.placeLat, + queryId: $0.queryId, queryType: $0.queryType) }) return searchCellModel @@ -156,7 +166,8 @@ final class AddGeofenceViewModel: AddGeofenceViewModelProcotol { if let id = selectedItem.placeId { let result = try await searchService.getPlace(with: id) guard let result else { return false} - let mapModel = MapModel(model: result) + let model = SearchPresentation(model: result) + let mapModel = MapModel(model: model) self.delegate?.selectedPlaceResult(mapModel: mapModel) return true } else if selectedItem.lat != nil { @@ -166,7 +177,8 @@ final class AddGeofenceViewModel: AddGeofenceViewModelProcotol { return true } else { - let result = await searchService.searchText(text: selectedItem.locationName ?? "", userLat: lat, userLong: long) + let mapCenter = UserDefaultsHelper.getObject(value: LocationCoordinate2D.self, key: .mapCenter) + let result = await searchService.searchText(text: selectedItem.locationName ?? "", userLat: mapCenter != nil ? mapCenter?.latitude : lat, userLong: mapCenter != nil ? mapCenter?.longitude : long, queryId: selectedItem.queryId) self.presentation = [] switch result { diff --git a/LocationServices/LocationServices/Scenes/Geofence/SubViews/GeofenceDashboard/Controller/GeofenceDashboardVC.swift b/LocationServices/LocationServices/Scenes/Geofence/SubViews/GeofenceDashboard/Controller/GeofenceDashboardVC.swift index 9f81badc..a38081ca 100644 --- a/LocationServices/LocationServices/Scenes/Geofence/SubViews/GeofenceDashboard/Controller/GeofenceDashboardVC.swift +++ b/LocationServices/LocationServices/Scenes/Geofence/SubViews/GeofenceDashboard/Controller/GeofenceDashboardVC.swift @@ -82,11 +82,18 @@ final class GeofenceDashboardVC: UIViewController { $0.top.equalTo(headerView.snp.bottom).offset(10) $0.leading.trailing.bottom.equalToSuperview() } - - initialGeofenceView.snp.makeConstraints { - $0.centerY.equalToSuperview().multipliedBy(0.9) - $0.leading.equalToSuperview().offset(24) - $0.trailing.equalToSuperview().offset(-24) + if UIDevice.current.userInterfaceIdiom == .pad { + initialGeofenceView.snp.makeConstraints { + $0.centerY.equalToSuperview().multipliedBy(0.9) + $0.leading.equalToSuperview().offset(24) + $0.trailing.equalToSuperview().offset(-24) + } + } + else { + initialGeofenceView.snp.makeConstraints { + $0.top.leading.equalTo(view.safeAreaLayoutGuide).offset(16) + $0.trailing.bottom.equalTo(view.safeAreaLayoutGuide).offset(-16) + } } } diff --git a/LocationServices/LocationServices/Scenes/Geofence/SubViews/GeofenceDashboard/Views/InitialGeofenceView.swift b/LocationServices/LocationServices/Scenes/Geofence/SubViews/GeofenceDashboard/Views/InitialGeofenceView.swift index 0ad5ae9a..43b7cff1 100644 --- a/LocationServices/LocationServices/Scenes/Geofence/SubViews/GeofenceDashboard/Views/InitialGeofenceView.swift +++ b/LocationServices/LocationServices/Scenes/Geofence/SubViews/GeofenceDashboard/Views/InitialGeofenceView.swift @@ -29,9 +29,9 @@ final class InitialGeofenceView: UIView { textAlignment: .center) private let detailLabel = AmazonLocationLabel(labelText: """ - Add a geofence to get notified when your device - enters or exits it - """, + Add a geofence to get notified when your device + enters or exits it + """, font: UIFont.amazonFont(type: .regular, size: 13), isMultiline: true, fontColor: .searchBarTintColor, @@ -61,7 +61,7 @@ final class InitialGeofenceView: UIView { self.addSubview(geofenceButton) iconContainerView.snp.makeConstraints { - $0.top.equalToSuperview() + $0.top.equalToSuperview().offset(10) $0.centerX.equalToSuperview() $0.height.width.equalTo(96) } @@ -78,14 +78,15 @@ final class InitialGeofenceView: UIView { detailLabel.snp.makeConstraints { $0.top.equalTo(titleLabel.snp.bottom).offset(16) - $0.height.equalTo(36) - $0.leading.trailing.equalToSuperview() + $0.centerX.equalToSuperview() + $0.width.lessThanOrEqualTo(340) } geofenceButton.snp.makeConstraints { - $0.top.equalTo(detailLabel.snp.bottom).offset(16) - $0.leading.trailing.bottom.equalToSuperview() + $0.top.greaterThanOrEqualTo(detailLabel.snp.bottom).offset(30) + $0.leading.trailing.equalToSuperview() $0.height.equalTo(48) + $0.bottom.equalToSuperview().offset(-10) } } diff --git a/LocationServices/LocationServices/Scenes/Geofence/Views/GeofenceView.swift b/LocationServices/LocationServices/Scenes/Geofence/Views/GeofenceView.swift index 691f38c9..3164922b 100644 --- a/LocationServices/LocationServices/Scenes/Geofence/Views/GeofenceView.swift +++ b/LocationServices/LocationServices/Scenes/Geofence/Views/GeofenceView.swift @@ -159,7 +159,7 @@ final class GeofenceMapView: UIView { } func reloadMap() { - mapView.setupMapView() + mapView.setupMapView(locateMe: false) deselectAnnotation() amazonMapLogo.tintColor = GeneralHelper.getAmazonMapLogo() } diff --git a/LocationServices/LocationServices/Scenes/Settings/Subviews/MapStyle/Controller/MapStyleVC.swift b/LocationServices/LocationServices/Scenes/Settings/Subviews/MapStyle/Controller/MapStyleVC.swift index 13820810..739bf652 100644 --- a/LocationServices/LocationServices/Scenes/Settings/Subviews/MapStyle/Controller/MapStyleVC.swift +++ b/LocationServices/LocationServices/Scenes/Settings/Subviews/MapStyle/Controller/MapStyleVC.swift @@ -36,6 +36,7 @@ final class MapStyleVC: UIViewController { }() var colorSegment: ColorSegmentControl? = nil var politicalView = PoliticalView() + var languageView = LanguageView() var isLargerPad: Bool { max(UIScreen.main.bounds.size.width, UIScreen.main.bounds.size.height) > largerPadSideSizeThreshold @@ -133,6 +134,7 @@ final class MapStyleVC: UIViewController { self.view.addSubview(collectionView) self.view.addSubview(colorSegment!) self.view.addSubview(politicalView) + self.view.addSubview(languageView) collectionView.snp.makeConstraints { if isPad { @@ -162,7 +164,14 @@ final class MapStyleVC: UIViewController { $0.width.equalToSuperview() } + languageView.snp.makeConstraints { + $0.top.equalTo(politicalView.snp.bottom).offset(50) + $0.centerX.equalToSuperview() + $0.width.equalToSuperview() + } + politicalView.viewController = self + languageView.viewController = self } } diff --git a/LocationServices/LocationServices/Scenes/Settings/Subviews/MapStyle/Models/MapStyleTypes+Image.swift b/LocationServices/LocationServices/Scenes/Settings/Subviews/MapStyle/Models/MapStyleTypes+Image.swift index 1a6f4538..45513432 100644 --- a/LocationServices/LocationServices/Scenes/Settings/Subviews/MapStyle/Models/MapStyleTypes+Image.swift +++ b/LocationServices/LocationServices/Scenes/Settings/Subviews/MapStyle/Models/MapStyleTypes+Image.swift @@ -11,13 +11,13 @@ extension MapStyleImages { var image: UIImage { switch self { case .standard: - return .streetMapLayer + return .standardMapLayer case .monochrome: - return .light_gray_map_layer + return .monochromeMapLayer case .hybrid: - return .hybird_map_layer + return .hybridMapLayer case .satellite: - return .here_imagerey_map_layer + return .satelliteMapLayer } } } diff --git a/LocationServices/LocationServices/Scenes/Settings/Subviews/MapStyle/Models/MapStyleTypes.swift b/LocationServices/LocationServices/Scenes/Settings/Subviews/MapStyle/Models/MapStyleTypes.swift index d2ba1bb7..25ab5bc4 100644 --- a/LocationServices/LocationServices/Scenes/Settings/Subviews/MapStyle/Models/MapStyleTypes.swift +++ b/LocationServices/LocationServices/Scenes/Settings/Subviews/MapStyle/Models/MapStyleTypes.swift @@ -46,18 +46,101 @@ struct PoliticalViewType: Codable { let PoliticalViewTypes: [PoliticalViewType] = [ + PoliticalViewType(countryCode: "", flagCode: "", fullName: "No Political View", politicalDescription: ""), PoliticalViewType(countryCode: "ARG", flagCode: "AR", fullName: "Argentina", politicalDescription: "Argentina's view on the Southern Patagonian Ice Field and Tierra Del Fuego, including the Falkland Islands, South Georgia, and South Sandwich Islands"), + PoliticalViewType(countryCode: "CYP", flagCode: "CY", fullName: "Cyprus", politicalDescription: "Cyprus's view on ..."), PoliticalViewType(countryCode: "EGY", flagCode: "EG", fullName: "Egypt", politicalDescription: "Egypt's view on Bir Tawil"), + PoliticalViewType(countryCode: "GEO", flagCode: "GE", fullName: "Georgia", politicalDescription: "Georgia's view on ..."), + PoliticalViewType(countryCode: "GRC", flagCode: "GR", fullName: "Greece", politicalDescription: "Greece's view on ..."), PoliticalViewType(countryCode: "IND", flagCode: "IN", fullName: "India", politicalDescription: "India's view on Gilgit-Baltistan"), PoliticalViewType(countryCode: "KEN", flagCode: "KE", fullName: "Kenya", politicalDescription: "Kenya's view on the Ilemi Triangle"), PoliticalViewType(countryCode: "MAR", flagCode: "MA", fullName: "Morocco", politicalDescription: "Morocco's view on Western Sahara"), + PoliticalViewType(countryCode: "PSE", flagCode: "PS", fullName: "Palestine", politicalDescription: "Palestine's view on ..."), PoliticalViewType(countryCode: "RUS", flagCode: "RU", fullName: "Russia", politicalDescription: "Russia's view on Crimea"), PoliticalViewType(countryCode: "SDN", flagCode: "SD", fullName: "Sudan", politicalDescription: "Sudan's view on the Halaib Triangle"), PoliticalViewType(countryCode: "SRB", flagCode: "RS", fullName: "Serbia", politicalDescription: "Serbia's view on Kosovo, Vukovar, and Sarengrad Islands"), PoliticalViewType(countryCode: "SUR", flagCode: "SR", fullName: "Suriname", politicalDescription: "Suriname's view on the Courantyne Headwaters and Lawa Headwaters"), PoliticalViewType(countryCode: "SYR", flagCode: "SY", fullName: "Syria", politicalDescription: "Syria's view on the Golan Heights"), - PoliticalViewType(countryCode: "TUR", flagCode: "TR", fullName: "Turkey", politicalDescription: "Turkey's view on Cyprus and Northern Cyprus"), + PoliticalViewType(countryCode: "TUR", flagCode: "TR", fullName: "Türkiye", politicalDescription: "Türkiye's view on Cyprus and Northern Cyprus"), PoliticalViewType(countryCode: "TZA", flagCode: "TZ", fullName: "Tanzania", politicalDescription: "Tanzania's view on Lake Malawi"), PoliticalViewType(countryCode: "URY", flagCode: "UY", fullName: "Uruguay", politicalDescription: "Uruguay's view on Rincon de Artigas"), - PoliticalViewType(countryCode: "VNM", flagCode: "VN", fullName: "Vietnam", politicalDescription: "Vietnam's view on the Paracel Islands and Spratly Islands") ] + + +struct LanguageSwitcherData: Codable { + let value: String + let label: String +} + +let languageSwitcherData: [LanguageSwitcherData] = [ + LanguageSwitcherData(value: "en", label: "English"), + LanguageSwitcherData(value: "de", label: "Deutsch"), + LanguageSwitcherData(value: "es", label: "Español"), + LanguageSwitcherData(value: "fr", label: "Français"), + LanguageSwitcherData(value: "it", label: "Italiano"), + LanguageSwitcherData(value: "pt", label: "Português"), + LanguageSwitcherData(value: "zh", label: "简体中文"), + LanguageSwitcherData(value: "zh-Hant", label: "繁體中文"), + LanguageSwitcherData(value: "ja", label: "日本語"), + LanguageSwitcherData(value: "ko", label: "한국어"), + LanguageSwitcherData(value: "ar", label: "العربية"), + LanguageSwitcherData(value: "he", label: "עברית"), + LanguageSwitcherData(value: "hi", label: "हिन्दी"), + LanguageSwitcherData(value: "as", label: "অসমীয়া"), + LanguageSwitcherData(value: "az", label: "Azərbaycan dili"), + LanguageSwitcherData(value: "be", label: "Беларуская"), + LanguageSwitcherData(value: "bg", label: "Български"), + LanguageSwitcherData(value: "bn", label: "বাংলা"), + LanguageSwitcherData(value: "bs", label: "Bosanski"), + LanguageSwitcherData(value: "ca", label: "Català"), + LanguageSwitcherData(value: "cs", label: "Čeština"), + LanguageSwitcherData(value: "cy", label: "Cymraeg"), + LanguageSwitcherData(value: "da", label: "Dansk"), + LanguageSwitcherData(value: "el", label: "Ελληνικά"), + LanguageSwitcherData(value: "et", label: "Eesti"), + LanguageSwitcherData(value: "eu", label: "Euskara"), + LanguageSwitcherData(value: "fi", label: "Suomi"), + LanguageSwitcherData(value: "fo", label: "Føroyskt"), + LanguageSwitcherData(value: "ga", label: "Gaeilge"), + LanguageSwitcherData(value: "gl", label: "Galego"), + LanguageSwitcherData(value: "gn", label: "Avañe'ẽ"), + LanguageSwitcherData(value: "gu", label: "ગુજરાતી"), + LanguageSwitcherData(value: "hr", label: "Hrvatski"), + LanguageSwitcherData(value: "hu", label: "Magyar"), + LanguageSwitcherData(value: "hy", label: "Հայերեն"), + LanguageSwitcherData(value: "id", label: "Bahasa Indonesia"), + LanguageSwitcherData(value: "is", label: "Íslenska"), + LanguageSwitcherData(value: "ka", label: "ქართული"), + LanguageSwitcherData(value: "kk", label: "Қазақ тілі"), + LanguageSwitcherData(value: "km", label: "ខ្មែរ"), + LanguageSwitcherData(value: "kn", label: "ಕನ್ನಡ"), + LanguageSwitcherData(value: "ky", label: "Кыргызча"), + LanguageSwitcherData(value: "lt", label: "Lietuvių"), + LanguageSwitcherData(value: "lv", label: "Latviešu"), + LanguageSwitcherData(value: "mk", label: "Македонски"), + LanguageSwitcherData(value: "ml", label: "മലയാളം"), + LanguageSwitcherData(value: "mr", label: "मराठी"), + LanguageSwitcherData(value: "ms", label: "Bahasa Melayu"), + LanguageSwitcherData(value: "mt", label: "Malti"), + LanguageSwitcherData(value: "my", label: "မြန်မာစာ"), + LanguageSwitcherData(value: "nl", label: "Nederlands"), + LanguageSwitcherData(value: "no", label: "Norsk"), + LanguageSwitcherData(value: "or", label: "ଓଡ଼ିଆ"), + LanguageSwitcherData(value: "pa", label: "ਪੰਜਾਬੀ"), + LanguageSwitcherData(value: "pl", label: "Polski"), + LanguageSwitcherData(value: "ro", label: "Română"), + LanguageSwitcherData(value: "ru", label: "Русский"), + LanguageSwitcherData(value: "sk", label: "Slovenčina"), + LanguageSwitcherData(value: "sl", label: "Slovenščina"), + LanguageSwitcherData(value: "sq", label: "Shqip"), + LanguageSwitcherData(value: "sr", label: "Српски"), + LanguageSwitcherData(value: "sv", label: "Svenska"), + LanguageSwitcherData(value: "ta", label: "தமிழ்"), + LanguageSwitcherData(value: "te", label: "తెలుగు"), + LanguageSwitcherData(value: "th", label: "ไทย"), + LanguageSwitcherData(value: "tr", label: "Türkçe"), + LanguageSwitcherData(value: "uk", label: "Українська"), + LanguageSwitcherData(value: "uz", label: "Oʻzbek"), + LanguageSwitcherData(value: "vi", label: "Tiếng Việt") +] + diff --git a/LocationServices/LocationServices/Scenes/Tracking/Views/TrackingViews.swift b/LocationServices/LocationServices/Scenes/Tracking/Views/TrackingViews.swift index 5619759e..f9c63c07 100644 --- a/LocationServices/LocationServices/Scenes/Tracking/Views/TrackingViews.swift +++ b/LocationServices/LocationServices/Scenes/Tracking/Views/TrackingViews.swift @@ -139,7 +139,7 @@ final class TrackingMapView: UIView { } func reloadMap() { - mapView.setupMapView() + mapView.setupMapView(locateMe: false) amazonMapLogo.tintColor = GeneralHelper.getAmazonMapLogo() } diff --git a/LocationServices/LocationServices/Services/LocationSearchService.swift b/LocationServices/LocationServices/Services/LocationSearchService.swift index 060ecf5e..058399d0 100755 --- a/LocationServices/LocationServices/Services/LocationSearchService.swift +++ b/LocationServices/LocationServices/Services/LocationSearchService.swift @@ -13,7 +13,7 @@ enum LocationServiceConstant { } protocol AWSLocationSearchService { - func searchTextRequest(text: String, userLat: Double?, userLong: Double?) async throws -> SearchTextOutput? + func searchTextRequest(text: String, userLat: Double?, userLong: Double?, queryId: String?) async throws -> SearchTextOutput? func searchWithSuggestRequest(text: String, userLat: Double?, userLong: Double?) async throws -> SuggestOutput? @@ -26,7 +26,7 @@ extension AWSLocationSearchService { func searchTextRequest(text: String, userLat: Double?, - userLong: Double?) async throws -> SearchTextOutput? { + userLong: Double?, queryId: String? = nil) async throws -> SearchTextOutput? { var biasPosition: [Double]? = nil if let lat = userLat, let long = userLong { biasPosition = [long, lat] @@ -35,7 +35,7 @@ extension AWSLocationSearchService { biasPosition = [AppConstants.amazonHqMapPosition.longitude, AppConstants.amazonHqMapPosition.latitude] } let politicalView = UserDefaultsHelper.getObject(value: PoliticalViewType.self, key: .politicalView) - let input = SearchTextInput(biasPosition: biasPosition, language: Locale.currentLanguageIdentifier(), politicalView: politicalView?.countryCode, queryText: text) + let input = SearchTextInput(biasPosition: queryId == nil ? biasPosition: nil, language: queryId == nil ? Locale.currentLanguageIdentifier() : nil, politicalView: queryId == nil ? politicalView?.countryCode : nil, queryId: queryId, queryText: queryId == nil ? text : nil) if let client = AmazonLocationClient.getPlacesClient() { let result = try await client.searchText(input: input) @@ -67,7 +67,7 @@ extension AWSLocationSearchService { func getPlaceRequest(with placeId: String) async throws -> GetPlaceOutput? { let politicalView = UserDefaultsHelper.getObject(value: PoliticalViewType.self, key: .politicalView) - let input = GetPlaceInput(language: Locale.currentLanguageIdentifier(), placeId: placeId, politicalView: politicalView?.countryCode) + let input = GetPlaceInput(additionalFeatures: [GeoPlacesClientTypes.GetPlaceAdditionalFeature.contact], language: Locale.currentLanguageIdentifier(), placeId: placeId, politicalView: politicalView?.countryCode) if let client = AmazonLocationClient.getPlacesClient() { let result = try await client.getPlace(input: input) return result diff --git a/LocationServices/LocationServices/Services/RoutingService.swift b/LocationServices/LocationServices/Services/RoutingService.swift index 6843cd2a..20ede0e6 100644 --- a/LocationServices/LocationServices/Services/RoutingService.swift +++ b/LocationServices/LocationServices/Services/RoutingService.swift @@ -31,7 +31,7 @@ extension AWSRoutingServiceProtocol { let destination = [destinationPosition.longitude, destinationPosition.latitude] let legAdditionalFeatures: [GeoRoutesClientTypes.RouteLegAdditionalFeature] = [.travelStepInstructions, .summary] - let input = CalculateRoutesInput(avoid: routeAvoidanceOptions, departNow: true, destination: destination, instructionsMeasurementSystem: .metric, legAdditionalFeatures: legAdditionalFeatures, legGeometryFormat: GeoRoutesClientTypes.GeometryFormat.simple, origin: origin, travelStepType: .default) + let input = CalculateRoutesInput(avoid: routeAvoidanceOptions, departNow: true, destination: destination, instructionsMeasurementSystem: .metric, legAdditionalFeatures: legAdditionalFeatures, legGeometryFormat: .simple, maxAlternatives: 0, origin: origin, travelMode: travelMode, travelStepType: .default) if let client = AmazonLocationClient.getRoutesClient() { let result = try await client.calculateRoutes(input: input) diff --git a/LocationServices/LocationServices/Views/Common/MapView/DefaultCommonMapView.swift b/LocationServices/LocationServices/Views/Common/MapView/DefaultCommonMapView.swift index a8b1cffe..1d6f4c59 100644 --- a/LocationServices/LocationServices/Views/Common/MapView/DefaultCommonMapView.swift +++ b/LocationServices/LocationServices/Views/Common/MapView/DefaultCommonMapView.swift @@ -73,15 +73,17 @@ final class DefaultCommonMapView: UIView, NavigationMapProtocol { } } - func setupMapView() { + func setupMapView(locateMe: Bool = true) { DispatchQueue.main.async { [self] in mapView.styleURL = DefaultMapStyles.getMapStyleUrl() - locateMeAction() + if locateMe { + locateMeAction(force: true) + } mapView.showsUserLocation = true } } - func isLocateMeButtonDisabled(state: Bool) { + func isLocateMeButtonDisabled(state: Bool, animatedUserLocation: Bool = true) { guard !state, let userCoordinates = mapView.userLocation?.coordinate, @@ -90,7 +92,7 @@ final class DefaultCommonMapView: UIView, NavigationMapProtocol { return } - setMapCenter(userCoordinates: userCoordinates) + setMapCenter(userCoordinates: userCoordinates, animated: animatedUserLocation) } func grantedLocationPermissions() { @@ -166,7 +168,7 @@ extension DefaultCommonMapView: MLNMapViewDelegate { let userCoordinates = userLocation?.coordinate else { return } wasCenteredByUserLocation = true - setMapCenter(userCoordinates: userCoordinates) + setMapCenter(userCoordinates: userCoordinates, animated: true) case .turnByTurnNavigation: guard (userLocation?.coordinate) != nil else { return } } @@ -193,16 +195,37 @@ extension DefaultCommonMapView: MLNMapViewDelegate { geofenceAnnotationView.update(mapView: mapView) }) } + + func mapView(_ mapView: MLNMapView, didFinishLoading style: MLNStyle) { + GeneralHelper.setMapLanguage(mapView: mapView, style: style) + } + + func mapViewDidFinishRenderingFrame(_ mapView: MLNMapView, fullyRendered: Bool) { + if fullyRendered { + if let style = mapView.style { + GeneralHelper.setMapLanguage(mapView: mapView, style: style) + } + } + } + } extension DefaultCommonMapView { - @objc func locateMeAction() { - let state = mapView.locationManager.authorizationStatus == .authorizedWhenInUse - isLocateMeButtonDisabled(state: !state) + @objc func locateMeAction(force: Bool = false) { + let action = { [weak self] in + guard let self else { return } + let state = self.mapView.locationManager.authorizationStatus == .authorizedWhenInUse + self.isLocateMeButtonDisabled(state: !state, animatedUserLocation: !force) + } + + guard !force else { + action() + return + } } - private func setMapCenter(userCoordinates: CLLocationCoordinate2D) { - mapView.setCenter(userCoordinates, zoomLevel: Constant.locateMeMapZoomValue, direction: mapView.direction, animated: true) { [weak self] in + private func setMapCenter(userCoordinates: CLLocationCoordinate2D, animated: Bool) { + mapView.setCenter(userCoordinates, zoomLevel: Constant.locateMeMapZoomValue, direction: mapView.direction, animated: animated) { [weak self] in switch self?.mapMode { case .search, .none: self?.mapView.userTrackingMode = .follow diff --git a/LocationServices/LocationServices/Views/Common/POICardView.swift b/LocationServices/LocationServices/Views/Common/POICardView.swift index 819aa788..4440e5b0 100755 --- a/LocationServices/LocationServices/Views/Common/POICardView.swift +++ b/LocationServices/LocationServices/Views/Common/POICardView.swift @@ -36,6 +36,39 @@ final class POICardView: UIView { self.dotView.isHidden = true self.distanceLabel.isHidden = true } + + var height: CGFloat = 200 + + if let place = dataModel.place { + if let schedule = place.openingHours { + scheduleDetail.text = schedule.map { $0.display!.joined(separator: "\n") }.joined(separator: "\n") + height += 40 // Additional padding + } + + if let websites = place.contacts?.websites { + webLabel.text = websites.map { $0.value! }.joined(separator: "\n") + height += 40 // Additional padding + } + + if let phones = place.contacts?.phones { + phoneLabel.text = phones.map { $0.value! }.joined(separator: "\n") + height += 40 // Additional padding + } + + // Assuming label widths are the same; adjust as needed + let labelWidth: CGFloat = scheduleDetail.frame.width // Use appropriate frame width + let font = scheduleDetail.font ?? .amazonFont(type: .regular, size: 13) + + // Calculate precise heights for each label + height += calculateHeight(for: scheduleDetail.text, font: font, width: labelWidth) + height += calculateHeight(for: webLabel.text, font: font, width: labelWidth) + height += calculateHeight(for: phoneLabel.text, font: font, width: labelWidth) + } + + scheduleTitleContainer.isHidden = !(scheduleDetail.text != nil && !scheduleDetail.text!.isEmpty) + scheduleValuesContainer.isHidden = !(scheduleDetail.text != nil && !scheduleDetail.text!.isEmpty) + webValuesContainer.isHidden = !(webLabel.text != nil && !webLabel.text!.isEmpty) + phoneValuesContainer.isHidden = !(phoneLabel.text != nil && !phoneLabel.text!.isEmpty) errorLabel.text = errorMessage errorLabel.isHidden = errorMessage == nil @@ -45,11 +78,23 @@ final class POICardView: UIView { let hideDistanceValuesContainer = !hasDistanceValues && !isLoadingData distanceValuesContainer.isHidden = hideDistanceValuesContainer - let sizeClass: POICardVC.DetentsSizeClass = !hideDistanceValuesContainer ? .allInfo : .noDistanceValues - delegate?.updateSizeClass(sizeClass) + delegate?.setPOIHeight(height) } } + // Helper function to calculate height for each label + func calculateHeight(for text: String?, font: UIFont, width: CGFloat) -> CGFloat { + guard let text = text, !text.isEmpty else { return 0 } + let textAttributes: [NSAttributedString.Key: Any] = [.font: font] + let boundingRect = (text as NSString).boundingRect( + with: CGSize(width: width, height: .greatestFiniteMagnitude), + options: [.usesLineFragmentOrigin, .usesFontLeading], + attributes: textAttributes, + context: nil + ) + return ceil(boundingRect.height) // Round up to the nearest whole number + } + var isLoadingData: Bool = false { didSet { placeholderAnimator.setupAnimationStatus(isActive: isLoadingData) @@ -103,12 +148,22 @@ final class POICardView: UIView { return label }() + private lazy var copyIconButton: UIButton = { + let button = UIButton(type: .system) + button.tintColor = .lsGrey + button.setImage(.copyIcon, for: .normal) + button.addTarget(self, action: #selector(copyButtonAction), for: .touchUpInside) + button.isUserInteractionEnabled = true + return button + }() + private let stackView: UIStackView = { let stackView = UIStackView() stackView.axis = .vertical stackView.spacing = 8 stackView.distribution = .equalSpacing stackView.alignment = .leading + stackView.isUserInteractionEnabled = true return stackView }() @@ -129,6 +184,7 @@ final class POICardView: UIView { private let durationIconView: UIImageView = { let iv = UIImageView(image: .carIcon) + iv.tintColor = .black iv.contentMode = .scaleAspectFit return iv }() @@ -143,6 +199,116 @@ final class POICardView: UIView { return label }() + private let detailsStackView: UIStackView = { + let stackView = UIStackView() + stackView.axis = .vertical + stackView.spacing = 8 + stackView.distribution = .equalSpacing + stackView.alignment = .leading + return stackView + }() + + private var detailsSeparatorView: UIView = { + let view = UIView() + view.backgroundColor = .lsLight3 + return view + }() + + private let scheduleValuesContainer: UIView = { + let view = UIView() + view.backgroundColor = .clear + return view + }() + + private let scheduleTitleContainer: UIView = { + let view = UIView() + view.backgroundColor = .clear + return view + }() + + private let scheduleIconView: UIImageView = { + let iv = UIImageView(image: UIImage(systemName: "clock")) + iv.contentMode = .scaleAspectFit + iv.tintColor = .systemGray + return iv + }() + + private let scheduleTitleLabel: UILabel = { + let label = UILabel() + label.textAlignment = .left + label.font = .amazonFont(type: .regular, size: 13) + label.textColor = .black + label.text = "Schedule" + return label + }() + + private lazy var expandIconView: UIButton = { + let button = UIButton(type: .system) + button.tintColor = .lsGrey + button.setImage(.expandDownIcon, for: .normal) + button.addTarget(self, action: #selector(chevronButtonAction), for: .touchUpInside) + return button + }() + + private let scheduleDetail: UILabel = { + let label = UILabel() + label.textAlignment = .left + label.font = .amazonFont(type: .regular, size: 13) + label.textColor = .black + label.numberOfLines = 0 + return label + }() + + private let webValuesContainer: UIView = { + let view = UIView() + view.backgroundColor = .clear + return view + }() + + private let webIconView: UIImageView = { + let iv = UIImageView(image: UIImage(systemName: "globe")) + iv.contentMode = .scaleAspectFit + iv.tintColor = .systemGray + return iv + }() + + private let webLabel: UITextView = { + let textView = UITextView() + textView.isEditable = false + textView.isScrollEnabled = false + textView.dataDetectorTypes = [.link] + textView.backgroundColor = .searchBarBackgroundColor + textView.linkTextAttributes = [.foregroundColor: UIColor.lsPrimary] + textView.font = .amazonFont(type: .regular, size: 13) + textView.textAlignment = .left + return textView + }() + + private let phoneValuesContainer: UIView = { + let view = UIView() + view.backgroundColor = .clear + return view + }() + + private let phoneIconView: UIImageView = { + let iv = UIImageView(image: UIImage(systemName: "phone")) + iv.contentMode = .scaleAspectFit + iv.tintColor = .systemGray + return iv + }() + + private let phoneLabel: UITextView = { + let textView = UITextView() + textView.isEditable = false + textView.isScrollEnabled = false + textView.dataDetectorTypes = [.phoneNumber] + textView.backgroundColor = .searchBarBackgroundColor + textView.linkTextAttributes = [.foregroundColor: UIColor.lsPrimary] + textView.font = .amazonFont(type: .regular, size: 13) + textView.textAlignment = .left + return textView + }() + private let errorLabel: UILabel = { let label = UILabel() label.textAlignment = .left @@ -234,6 +400,8 @@ final class POICardView: UIView { return PlaceholderAnimator(dataViews: dataViews, placeholderViews: placeholderViews) }() + var scheduleDetailHeight = 60 + convenience init(titleTopOffset: CGFloat, isCloseButtonHidden: Bool) { self.init() self.titleTopOffset = titleTopOffset @@ -257,22 +425,45 @@ final class POICardView: UIView { func setupViews() { self.addSubview(containerView) - containerView.addSubview(topStackView) - topStackView.addArrangedSubview(headerView) headerView.addSubview(closeButton) headerView.addSubview(poiTitle) + containerView.addSubview(topStackView) + containerView.addSubview(infoButton) + + topStackView.addArrangedSubview(headerView) topStackView.addArrangedSubview(stackView) + stackView.addArrangedSubview(poiAddress) - + stackView.addSubview(copyIconButton) + + stackView.addArrangedSubview(errorLabel) stackView.addArrangedSubview(distanceValuesContainer) + distanceValuesContainer.addSubview(durationIconView) distanceValuesContainer.addSubview(dotView) distanceValuesContainer.addSubview(durationLabel) distanceValuesContainer.addSubview(distanceLabel) - stackView.addArrangedSubview(errorLabel) - containerView.addSubview(infoButton) + stackView.addArrangedSubview(detailsStackView) + + detailsStackView.addArrangedSubview(detailsSeparatorView) + + detailsStackView.addArrangedSubview(scheduleTitleContainer) + scheduleTitleContainer.addSubview(scheduleIconView) + scheduleTitleContainer.addSubview(scheduleTitleLabel) + scheduleTitleContainer.addSubview(expandIconView) + + detailsStackView.addArrangedSubview(scheduleValuesContainer) + scheduleValuesContainer.addSubview(scheduleDetail) + + detailsStackView.addArrangedSubview(webValuesContainer) + webValuesContainer.addSubview(webIconView) + webValuesContainer.addSubview(webLabel) + + detailsStackView.addArrangedSubview(phoneValuesContainer) + phoneValuesContainer.addSubview(phoneIconView) + phoneValuesContainer.addSubview(phoneLabel) containerView.addSubview(directionButton) directionButton.addSubview(buttonContainerView) @@ -310,6 +501,12 @@ final class POICardView: UIView { $0.height.greaterThanOrEqualTo(18) } + copyIconButton.snp.makeConstraints { + $0.height.equalTo(20) + $0.width.equalTo(18) + $0.leading.equalTo(poiAddress.snp.trailing).offset(10) + } + distanceValuesContainer.snp.makeConstraints { $0.height.equalTo(18) } @@ -335,6 +532,72 @@ final class POICardView: UIView { $0.leading.equalTo(durationIconView.snp.trailing).offset(10) } + detailsSeparatorView.snp.makeConstraints { + $0.height.equalTo(1) + $0.width.equalToSuperview().offset(10) + } + + detailsStackView.snp.makeConstraints { + $0.leading.trailing.equalToSuperview() + } + + scheduleIconView.snp.makeConstraints { + $0.top.equalToSuperview() + $0.leading.equalToSuperview() + $0.width.equalTo(18) + } + + scheduleTitleContainer.snp.makeConstraints { + $0.leading.trailing.equalToSuperview() + } + + scheduleTitleLabel.snp.makeConstraints { + $0.top.bottom.equalToSuperview() + $0.leading.equalTo(scheduleIconView.snp.trailing).offset(10) + } + + expandIconView.snp.makeConstraints { + $0.top.bottom.equalToSuperview() + $0.trailing.equalToSuperview() + $0.height.equalTo(12) + $0.width.equalTo(14) + } + + scheduleValuesContainer.snp.makeConstraints { + $0.height.equalTo(scheduleDetailHeight) + } + + scheduleDetail.snp.makeConstraints { + $0.top.bottom.equalToSuperview() + $0.trailing.equalToSuperview() + $0.leading.equalTo(scheduleIconView.snp.trailing).offset(10) + } + + webIconView.snp.makeConstraints { + $0.top.equalToSuperview().offset(10) + $0.leading.equalToSuperview() + $0.width.equalTo(18) + } + + webLabel.snp.makeConstraints { + $0.top.equalToSuperview() + $0.bottom.equalToSuperview() + $0.trailing.equalToSuperview() + $0.leading.equalTo(webIconView.snp.trailing).offset(10) + } + + phoneIconView.snp.makeConstraints { + $0.top.equalToSuperview().offset(10) + $0.leading.equalToSuperview() + $0.width.equalTo(18) + } + + phoneLabel.snp.makeConstraints { + $0.top.equalToSuperview() + $0.trailing.equalToSuperview() + $0.leading.equalTo(phoneIconView.snp.trailing).offset(10) + } + infoButton.snp.makeConstraints { $0.height.width.equalTo(13.5) $0.leading.equalTo(errorLabel.snp.trailing).offset(5) @@ -345,13 +608,13 @@ final class POICardView: UIView { $0.leading.equalToSuperview().offset(16) $0.trailing.equalToSuperview().offset(-16) $0.height.equalTo(48) - $0.top.equalTo(topStackView.snp.bottom).offset(25) + $0.bottom.equalToSuperview().offset(-10) } buttonContainerView.snp.makeConstraints { $0.height.equalTo(22) $0.width.equalTo(120) - $0.centerY.centerX.equalToSuperview() + $0.centerX.centerY.equalToSuperview() } directionIcon.snp.makeConstraints { @@ -381,17 +644,45 @@ final class POICardView: UIView { directionPlaceholderView.layer.cornerRadius = 4 durationPlaceholderView.layer.cornerRadius = 4 + + webLabel.delegate = self + phoneLabel.delegate = self + + chevronButtonAction() } } -extension POICardView { +extension POICardView: UITextViewDelegate { @objc func directionButtonAction() { delegate?.showDirectionView(seconDestination: dataModel) } + @objc private func copyButtonAction() { + UIPasteboard.general.string = "\(poiTitle.text ?? ""), \(poiAddress.text ?? "")" + } + @objc private func infoButtonAction() { guard let errorInfoMessage else { return } let model = AlertModel(title: StringConstant.locationPermissionDenied, message: errorInfoMessage, cancelButton: nil) delegate?.showAlert(model) } + + @objc private func chevronButtonAction() { + let labelWidth: CGFloat = scheduleDetail.frame.width // Use appropriate frame width + let font = scheduleDetail.font ?? .amazonFont(type: .regular, size: 13) + + scheduleDetail.isHidden.toggle() + expandIconView.setImage(scheduleDetail.isHidden ? .expandDownIcon : .expandUpIcon, for: .normal) + scheduleDetailHeight = Int(scheduleDetail.isHidden ? 0 : calculateHeight(for: scheduleDetail.text, font: font, width: labelWidth)) + scheduleValuesContainer.snp.updateConstraints { + $0.height.equalTo(scheduleDetailHeight) + } + UIView.animate(withDuration: 0.3) { + self.layoutIfNeeded() + } + } + + func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { + return true + } } diff --git a/LocationServices/LocationServicesTests/AddGeofenceViewModelTests.swift b/LocationServices/LocationServicesTests/AddGeofenceViewModelTests.swift index 0c49066e..e01b5ecd 100644 --- a/LocationServices/LocationServicesTests/AddGeofenceViewModelTests.swift +++ b/LocationServices/LocationServicesTests/AddGeofenceViewModelTests.swift @@ -7,6 +7,7 @@ import XCTest @testable import LocationServices +import AWSGeoPlaces final class AddGeofenceViewModelTests: XCTestCase { @@ -35,6 +36,7 @@ final class AddGeofenceViewModelTests: XCTestCase { var viewModelDelegate: AddGeofenceViewModelOutputProtocolMock! var userLocation: (lat: Double, long: Double)! var search: SearchPresentation! + var place: GetPlaceOutput! override func setUpWithError() throws { userLocation = (lat: 40.7487776237092, long: -73.98554260340953) @@ -50,6 +52,7 @@ final class AddGeofenceViewModelTests: XCTestCase { locationService = LocationAPIServiceMock(delay: Constants.apiRequestDuration) viewModelDelegate = AddGeofenceViewModelOutputProtocolMock() setupViewModel(with: []) + place = GetPlaceOutput(placeId: "ID", position: [-73.98554260340953, 40.7487776237092], title: "dummy place") } override func tearDownWithError() throws { @@ -305,7 +308,7 @@ final class AddGeofenceViewModelTests: XCTestCase { setupViewModel(with: [Constants.testGeofenceModel]) locationService.mockSearchTextResult = .success([search]) locationService.mockSearchTextWithSuggestionResult = .success([search]) - locationService.mockGetPlaceResult = .success(search) + locationService.mockGetPlaceResult = .success(place) _ = try await viewModel.searchWithSuggestion(text: "Times Square", userLat: userLocation.lat, userLong: userLocation.long) XCTWaiter().wait(until: { return self.viewModelDelegate.searchResultCalled @@ -329,7 +332,7 @@ final class AddGeofenceViewModelTests: XCTestCase { name: "Times Square") setupViewModel(with: [model]) locationService.mockSearchTextWithSuggestionResult = .success([search]) - locationService.mockGetPlaceResult = .success(search) + locationService.mockGetPlaceResult = .success(place) _ = try await viewModel.searchWithSuggestion(text: "Times Square", userLat: userLocation.lat, userLong: userLocation.long) XCTWaiter().wait(until: { return self.viewModelDelegate.searchResultCalled @@ -353,7 +356,7 @@ final class AddGeofenceViewModelTests: XCTestCase { name: "Times Square") setupViewModel(with: [model]) locationService.mockSearchTextWithSuggestionResult = .success([search]) - locationService.mockGetPlaceResult = .success(search) + locationService.mockGetPlaceResult = .success(place) _ = try await viewModel.searchWithSuggestion(text: "Times Square", userLat: userLocation.lat, userLong: userLocation.long) XCTWaiter().wait(until: { return self.viewModelDelegate.searchResultCalled diff --git a/LocationServices/LocationServicesTests/DirectionViewModelTests.swift b/LocationServices/LocationServicesTests/DirectionViewModelTests.swift index acc332b8..fe93c27d 100644 --- a/LocationServices/LocationServicesTests/DirectionViewModelTests.swift +++ b/LocationServices/LocationServicesTests/DirectionViewModelTests.swift @@ -164,7 +164,7 @@ final class DirectionViewModelTests: XCTestCase { func testSearchSelectedPlaceWith() async throws { locationService.mockSearchTextResult = .success([search]) - let model = SearchCellViewModel(searchType: .location, placeId: nil, locationName: "Times Square", locationDistance: 12, locationCountry: "USA", locationCity: "Manhattan", label: "Times Square", long: nil, lat: nil) + let model = SearchCellViewModel(searchType: .location, placeId: nil, locationName: "Times Square", locationDistance: 12, locationCountry: "USA", locationCity: "Manhattan", label: "Times Square", long: nil, lat: nil, queryId: nil, queryType: .none) let result = try await self.directionViewModel.searchSelectedPlaceWith(model, lat: self.userLocation.lat, long: self.userLocation.long) XCTAssertEqual(result, false, "Expected false") @@ -179,7 +179,7 @@ final class DirectionViewModelTests: XCTestCase { let legDetails = GeoRoutesClientTypes.RouteVehicleLegDetails(travelSteps: [step]) let routeLeg = GeoRoutesClientTypes.RouteLeg(travelMode: .car, vehicleLegDetails: legDetails) let route = GeoRoutesClientTypes.Route(legs: [routeLeg]) - let direction = DirectionPresentation(model: route, travelMode: .car) + let direction = try DirectionPresentation(model: route, travelMode: .car) routingService.putResult = [GeoRoutesClientTypes.RouteTravelMode.car: .success(direction)] if let result = try await directionViewModel.calculateRouteWith(destinationPosition: CLLocationCoordinate2D(latitude: 40.75803155895524, longitude: -73.9855533309874) , departurePosition: CLLocationCoordinate2D(latitude: 40.75803155895524, longitude: -73.9855533309874)) { diff --git a/LocationServices/LocationServicesTests/ExploreViewModelTests.swift b/LocationServices/LocationServicesTests/ExploreViewModelTests.swift index c744143c..b777bc1d 100644 --- a/LocationServices/LocationServicesTests/ExploreViewModelTests.swift +++ b/LocationServices/LocationServicesTests/ExploreViewModelTests.swift @@ -9,6 +9,7 @@ import XCTest @testable import LocationServices import CoreLocation import AWSGeoRoutes +import AWSGeoPlaces final class ExploreViewModelTests: XCTestCase { @@ -21,6 +22,7 @@ final class ExploreViewModelTests: XCTestCase { var delegate: MockExploreViewModelOutputDelegate! var userLocation: (lat: Double, long: Double)! var search: SearchPresentation! + var place: GetPlaceOutput! enum Constants { static let waitRequestDuration: TimeInterval = 10 static let apiRequestDuration: TimeInterval = 1 @@ -50,6 +52,8 @@ final class ExploreViewModelTests: XCTestCase { departureLocation = CLLocationCoordinate2D(latitude: 40.75790965683081, longitude: -73.98559624758715) destinationLocation = CLLocationCoordinate2D(latitude:40.75474012009525, longitude: -73.98387963388527) routeModel = RouteModel(departurePosition: departureLocation, destinationPosition: destinationLocation, travelMode: RouteTypes.car, avoidFerries: false, avoidTolls: false, isPreview: true, departurePlaceName: "Time Square", departurePlaceAddress: "Manhattan, NY 10036, United States", destinationPlaceName: "CUNY Graduate Center", destinationPlaceAddress: "365 5th Ave, New York, NY 10016, United States") + + place = GetPlaceOutput(placeId: "ID", position: [-73.98554260340953, 40.7487776237092], title: "dummy place") } override func tearDownWithError() throws { @@ -86,8 +90,8 @@ final class ExploreViewModelTests: XCTestCase { } func testReCalculateRouteReturnSuccess() async throws { - let direction = DirectionPresentation(model: GeoRoutesClientTypes.Route(), travelMode: .car) - locationService.mockGetPlaceResult = .success(search) + let direction = try DirectionPresentation(model: GeoRoutesClientTypes.Route(), travelMode: .car) + locationService.mockGetPlaceResult = .success(place) locationService.mockSearchWithPositionResult = .success([search]) routingService.putResult = [GeoRoutesClientTypes.RouteTravelMode.car: .success(direction)] exploreViewModel.activateRoute(route: routeModel) @@ -116,6 +120,7 @@ final class ExploreViewModelTests: XCTestCase { placeLong: departureLocation?.longitude, name: "My Location") locationService.mockSearchWithPositionResult = .success([search]) + locationService.mockGetPlaceResult = .success(place) await exploreViewModel.loadPlace(for: destinationLocation, userLocation: departureLocation) XCTWaiter().wait(until: { diff --git a/LocationServices/LocationServicesTests/GeofenceViewModelTests.swift b/LocationServices/LocationServicesTests/GeofenceViewModelTests.swift index a90b7195..17ab9488 100644 --- a/LocationServices/LocationServicesTests/GeofenceViewModelTests.swift +++ b/LocationServices/LocationServicesTests/GeofenceViewModelTests.swift @@ -103,7 +103,7 @@ final class GeofenceViewModelTests: XCTestCase { delegate.models = nil UserDefaultsHelper.setAppState(state: .initial) await viewModel.fetchListOfGeofences() - XCTAssertNil(delegate?.models) + XCTAssertTrue( delegate?.models == nil || delegate?.models?.count == 0) } func testFetchListOfGeofencesSignedInSuccess() async throws { diff --git a/LocationServices/LocationServicesTests/Mocks/LocationAPIServiceMock.swift b/LocationServices/LocationServicesTests/Mocks/LocationAPIServiceMock.swift index a9760597..4b5a4f32 100644 --- a/LocationServices/LocationServicesTests/Mocks/LocationAPIServiceMock.swift +++ b/LocationServices/LocationServicesTests/Mocks/LocationAPIServiceMock.swift @@ -7,22 +7,20 @@ import Foundation @testable import LocationServices -import AWSLocation - -class LocationAPIServiceMock: LocationServiceable { +import AWSGeoPlaces +class LocationAPIServiceMock: LocationServiceable { var mockSearchTextResult: Result<[SearchPresentation], Error> = .success([]) var mockSearchTextWithSuggestionResult: Result<[SearchPresentation], Error> = .success([]) var mockSearchWithPositionResult: Result<[SearchPresentation], Error> = .success([]) - var mockGetPlaceResult: Result = .success(nil) - + var mockGetPlaceResult: Result = .success(nil) let delay: TimeInterval init(delay: TimeInterval) { self.delay = delay } - func searchText(text: String, userLat: Double?, userLong: Double?) async -> Result<[SearchPresentation], Error> { + func searchText(text: String, userLat: Double?, userLong: Double?, queryId: String?) async -> Result<[SearchPresentation], Error> { return mockSearchTextResult } @@ -34,7 +32,7 @@ class LocationAPIServiceMock: LocationServiceable { return mockSearchWithPositionResult } - func getPlace(with placeId: String) async throws -> SearchPresentation? { + func getPlace(with placeId: String) async throws -> GetPlaceOutput? { switch mockGetPlaceResult { case .success(let model): return model @@ -42,5 +40,6 @@ class LocationAPIServiceMock: LocationServiceable { throw error } } + } diff --git a/LocationServices/LocationServicesTests/POICardViewModelTests.swift b/LocationServices/LocationServicesTests/POICardViewModelTests.swift index c964c262..8b91fa1b 100644 --- a/LocationServices/LocationServicesTests/POICardViewModelTests.swift +++ b/LocationServices/LocationServicesTests/POICardViewModelTests.swift @@ -45,7 +45,7 @@ final class POICardViewModelTests: XCTestCase { func testFetchDatasWithSuccess() async throws { pOICardViewModel.setUserLocation(lat: 40.4400930458457, long: -80.00348250162394) - let direction = DirectionPresentation(model: GeoRoutesClientTypes.Route(), travelMode: .car) + let direction = try DirectionPresentation(model: GeoRoutesClientTypes.Route(), travelMode: .car) routingService.putResult = [GeoRoutesClientTypes.RouteTravelMode.car: .success(direction)] try await pOICardViewModel.fetchDatas() @@ -69,6 +69,10 @@ class MockPOICardViewModelOutputDelegate: POICardViewModelOutputDelegate { } + func setPOIHeight(_ height: CGFloat) { + + } + func showAlert(_ model: AlertModel) { } diff --git a/LocationServices/LocationServicesTests/SearchViewModelTests.swift b/LocationServices/LocationServicesTests/SearchViewModelTests.swift index b03dbe69..62a49b08 100644 --- a/LocationServices/LocationServicesTests/SearchViewModelTests.swift +++ b/LocationServices/LocationServicesTests/SearchViewModelTests.swift @@ -8,6 +8,7 @@ import XCTest @testable import LocationServices import CoreLocation +import AWSGeoPlaces final class SearchViewModelTests: XCTestCase { @@ -16,6 +17,8 @@ final class SearchViewModelTests: XCTestCase { var locationService: LocationAPIServiceMock! var delegate: MockSearchViewModelOutputDelegate! var search: SearchPresentation! + var place: GetPlaceOutput! + enum Constants { static let waitRequestDuration: TimeInterval = 10 static let apiRequestDuration: TimeInterval = 1 @@ -38,6 +41,7 @@ final class SearchViewModelTests: XCTestCase { placeLat: userLocation?.latitude, placeLong: userLocation?.longitude, name: "Times Square") + place = GetPlaceOutput(placeId: "ID", position: [-73.98554260340953, 40.7487776237092], title: "dummy place") } override func tearDownWithError() throws { @@ -131,7 +135,7 @@ final class SearchViewModelTests: XCTestCase { func testGetSearchCellModelWithResults() async throws { locationService.mockSearchTextWithSuggestionResult = .success([search]) - locationService.mockGetPlaceResult = .success(search) + locationService.mockGetPlaceResult = .success(place) locationService.mockSearchTextResult = .success([search]) try await searchViewModel.searchWithSuggestion(text: "Times Square", userLat: userLocation.latitude, userLong: userLocation.longitude) XCTWaiter().wait(until: { @@ -142,7 +146,7 @@ final class SearchViewModelTests: XCTestCase { func testSearchSelectedPlaceWithPlaceId() async throws { locationService.mockSearchTextWithSuggestionResult = .success([search]) - locationService.mockGetPlaceResult = .success(search) + locationService.mockGetPlaceResult = .success(place) locationService.mockSearchWithPositionResult = .success([search]) locationService.mockSearchTextResult = .success([search]) try await searchViewModel.searchWithSuggestion(text: "Times Square", userLat: userLocation.latitude, userLong: userLocation.longitude) @@ -188,7 +192,7 @@ final class SearchViewModelTests: XCTestCase { name: "Times Square") locationService.mockSearchTextResult = .success([search]) locationService.mockSearchWithPositionResult = .success([search]) - locationService.mockGetPlaceResult = .success(search) + locationService.mockGetPlaceResult = .success(place) locationService.mockSearchTextWithSuggestionResult = .success([search]) locationService.mockSearchTextResult = .success([search]) _ = try await searchViewModel.searchWithSuggestion(text: "Times Square", userLat: userLocation.latitude, userLong: userLocation.longitude) diff --git a/LocationServices/LocationServicesUITests/Models/UITestRouteType.swift b/LocationServices/LocationServicesUITests/Models/UITestRouteType.swift index e9d5bd08..98c95d15 100644 --- a/LocationServices/LocationServicesUITests/Models/UITestRouteType.swift +++ b/LocationServices/LocationServicesUITests/Models/UITestRouteType.swift @@ -8,12 +8,14 @@ import Foundation enum RouteType { - case pedestrian, car, truck + case pedestrian, car, truck, scooter var containerId: String { switch self { case .pedestrian: return ViewsIdentifiers.Routing.pedestrianContainer + case .scooter: + return ViewsIdentifiers.Routing.scooterContainer case .car: return ViewsIdentifiers.Routing.carContainer case .truck: diff --git a/LocationServices/LocationServicesUITests/SearchUITests.swift b/LocationServices/LocationServicesUITests/SearchUITests.swift index 1da9ed82..8479d922 100644 --- a/LocationServices/LocationServicesUITests/SearchUITests.swift +++ b/LocationServices/LocationServicesUITests/SearchUITests.swift @@ -11,7 +11,7 @@ final class SearchUITests: LocationServicesUITests { enum Constants { static let addressName = "44 Boobialla Street, Corbie Hill, Australia" - static let geocode = "-31.9627092, 115.9248736" + static let geocode = "115.9248736, -31.9627092" static let searchText = "Rio Tinto" static let category = "School" static let timesSquareAddress = "New York Times Square"