From cae6a48116d7453354d9c5a0d4368d31c395096a Mon Sep 17 00:00:00 2001 From: Bandari Hari Swaroop Date: Fri, 20 Mar 2026 17:09:49 +0530 Subject: [PATCH 1/5] SDK V9 --- .../Helper/WayfindingHelper.swift | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Helper/WayfindingHelper.swift diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Helper/WayfindingHelper.swift b/SpacesWayFindingSDK-SampleApp-iOS/Helper/WayfindingHelper.swift new file mode 100644 index 0000000..ca73b60 --- /dev/null +++ b/SpacesWayFindingSDK-SampleApp-iOS/Helper/WayfindingHelper.swift @@ -0,0 +1,75 @@ +// +// WayfindingHelper.swift +// SpacesWayfindingSample +// +// Created by Cisco Spaces on 07/02/2025. +// + +import UIKit +import SpacesWayFindingApp + +class WayfindingHelper: NSObject { + + let spacesWayFinding = SpacesWayFinding(apiKey:,region: ) + + + + private var completion: ((MapWidgetViewController?, Error?) -> Void)? + + func getWidget(buildingParams: SpacesWayFindingParams, completion: ((MapWidgetViewController?, Error?) -> Void)? = nil) { + + self.completion = completion + + spacesWayFinding.selectBuilding(params: buildingParams) { [weak self] (state) in + switch state { + case .running: + print("Wayfinding is running") + self?.handleCompletion(error: nil) + break; + case .failedNoInternetConnection: + print("Failed: No internet") + case .failedValidation: + print("Validation failed") + case .off: + print("off") + // removeMapWidget(mapWidget: MapWidgetTheme) + default: + print("Current state: \(state)") + } + + } + + } +} + +extension WayfindingHelper { + + func handleCompletion(error: Error?) { + OperationQueue.main.addOperation { [weak self] in + if let error = error { + self?.completion?(nil, error) + return + } + + + let config = MapWidgetConfiguration.defaultConfiguration() + config.isJoystickEnabled = true + config.animationType=MapAnimationType.flyOver + config.minimumZoomLevel=12 + config.maximumZoomLevel=24 + + + let theme = MapWidgetTheme(accentColor: "000000", backgroundColor: "000000", foregroundColor: "000000", successColor: "FFFFFF", alertColor: "FFFFFF", dangerColor: "FFFFFF", infoColor: "FFFFFF") + + config.theme = theme + let mapWidget = MapWidgetViewController(configuration: config) + + mapWidget.mapEventsHandler = CustomMapEventHandler(mapWidget: mapWidget, wayfindingHelper: self) + mapWidget.pathFindingEventsHandler = CustomPathFindingEventsHandler(mapWidget: mapWidget) + mapWidget.mapExitHandler = CustomMapExitHandler(mapWidget: mapWidget) + + self?.completion?(mapWidget, nil) + self?.completion = nil + } + } +} From 300af653f037c7f13e782bff5f74a883a4563efe Mon Sep 17 00:00:00 2001 From: Bandari Hari Swaroop Date: Fri, 20 Mar 2026 17:28:41 +0530 Subject: [PATCH 2/5] V9 SDK Sample App --- .../AppDelegate.swift | 2 + .../BuildingsViewController.swift | 3 +- .../LoadingViewController.swift | 0 .../WidgetViewController.swift | 43 +++++++++------ .../CustomPathFindingEventsHandler.swift | 53 ------------------ .../CustomMapEventHandler.swift | 25 +++++++-- .../{ => Handlers}/CustomMapExitHandler.swift | 3 +- .../CustomPathFindingEventsHandler.swift | 32 +++++++++++ .../Helper/DataResetter.swift | 55 +++++++++++++++++++ 9 files changed, 140 insertions(+), 76 deletions(-) rename SpacesWayFindingSDK-SampleApp-iOS/{ => Controller}/BuildingsViewController.swift (97%) rename SpacesWayFindingSDK-SampleApp-iOS/{ => Controller}/LoadingViewController.swift (100%) rename SpacesWayFindingSDK-SampleApp-iOS/{ => Controller}/WidgetViewController.swift (79%) delete mode 100644 SpacesWayFindingSDK-SampleApp-iOS/CustomPathFindingEventsHandler.swift rename SpacesWayFindingSDK-SampleApp-iOS/{ => Handlers}/CustomMapEventHandler.swift (82%) rename SpacesWayFindingSDK-SampleApp-iOS/{ => Handlers}/CustomMapExitHandler.swift (73%) create mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomPathFindingEventsHandler.swift create mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Helper/DataResetter.swift diff --git a/SpacesWayFindingSDK-SampleApp-iOS/AppDelegate.swift b/SpacesWayFindingSDK-SampleApp-iOS/AppDelegate.swift index b64a4a9..efa9bff 100644 --- a/SpacesWayFindingSDK-SampleApp-iOS/AppDelegate.swift +++ b/SpacesWayFindingSDK-SampleApp-iOS/AppDelegate.swift @@ -13,6 +13,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + //DataResetter.resetAppData() // Override point for customization after application launch. return true } @@ -20,6 +21,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // MARK: UISceneSession Lifecycle func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. // Use this method to select a configuration to create the new scene with. return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) diff --git a/SpacesWayFindingSDK-SampleApp-iOS/BuildingsViewController.swift b/SpacesWayFindingSDK-SampleApp-iOS/Controller/BuildingsViewController.swift similarity index 97% rename from SpacesWayFindingSDK-SampleApp-iOS/BuildingsViewController.swift rename to SpacesWayFindingSDK-SampleApp-iOS/Controller/BuildingsViewController.swift index d75449d..bdf9ee7 100644 --- a/SpacesWayFindingSDK-SampleApp-iOS/BuildingsViewController.swift +++ b/SpacesWayFindingSDK-SampleApp-iOS/Controller/BuildingsViewController.swift @@ -34,6 +34,7 @@ class BuildingsViewController: UITableViewController { let building = buildings[indexPath.row] let params = SpacesWayFindingParams(building: building) + params.loggerLevel = LoggerLevel.all presentWidget(buildingParams: params) } } @@ -41,9 +42,9 @@ class BuildingsViewController: UITableViewController { extension BuildingsViewController { func presentWidget(buildingParams: SpacesWayFindingParams) { - let widget = WidgetViewController(buildingParams: buildingParams) widget.modalPresentationStyle = .fullScreen navigationController?.present(widget, animated: true) + } } diff --git a/SpacesWayFindingSDK-SampleApp-iOS/LoadingViewController.swift b/SpacesWayFindingSDK-SampleApp-iOS/Controller/LoadingViewController.swift similarity index 100% rename from SpacesWayFindingSDK-SampleApp-iOS/LoadingViewController.swift rename to SpacesWayFindingSDK-SampleApp-iOS/Controller/LoadingViewController.swift diff --git a/SpacesWayFindingSDK-SampleApp-iOS/WidgetViewController.swift b/SpacesWayFindingSDK-SampleApp-iOS/Controller/WidgetViewController.swift similarity index 79% rename from SpacesWayFindingSDK-SampleApp-iOS/WidgetViewController.swift rename to SpacesWayFindingSDK-SampleApp-iOS/Controller/WidgetViewController.swift index 32cf982..68153e6 100644 --- a/SpacesWayFindingSDK-SampleApp-iOS/WidgetViewController.swift +++ b/SpacesWayFindingSDK-SampleApp-iOS/Controller/WidgetViewController.swift @@ -30,7 +30,10 @@ class WidgetViewController: UIViewController { required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + + func getPois() -> [PoI]?{ + return self.wayfindingHelper.spacesWayFinding.getPoIs() + } override func viewDidLoad() { super.viewDidLoad() configureViews() @@ -43,14 +46,11 @@ class WidgetViewController: UIViewController { print(error) return } - self?.spinner.stopAnimating() self?.presentMapWidget(mapWidget: mapWidget) - print(self?.wayfindingHelper.spacesWayFinding.getPoIs()) - if let poi = self?.wayfindingHelper.spacesWayFinding.getPoIs().first { - // print(poi) // Will print your custom content - } + //print(self?.wayfindingHelper.spacesWayFinding.getPoIs()) + print(self?.wayfindingHelper.spacesWayFinding.getFloors()) print(self?.wayfindingHelper.spacesWayFinding.getFloor(level: 1)) //print(self?.wayfindingHelper.spacesWayFinding.getPoIById(id: "44dcc43e-b682-4fff-b8af-999b35f81997")) @@ -59,29 +59,43 @@ class WidgetViewController: UIViewController { if let floor = self?.wayfindingHelper.spacesWayFinding.getFloor(level: 3) { print(self?.wayfindingHelper.spacesWayFinding.getPoIs(floorId: floor.extraData[ "levelExternalIdentifier"] as? String ?? "fasfd")) - mapWidget.showFloor(floor: floor){error in + /** mapWidget.showFloor(floor: floor){error in print("32412erfdserror") print(error) - } + }*/ } + + if let building = self?.wayfindingHelper.spacesWayFinding.getBuildingById(id:self?.buildingParams.building.id ?? "") { + print("buildingafrewrfcasdzcx") + print(building.name) + /** mapWidget.showBuidling(building: building){error in + print("32412erfdserror") + print(error) + }*/ + } - var poi=self?.wayfindingHelper.spacesWayFinding.getPoIById(id: "44dcc43e-b682-4fff-b8af-999b35f81997") + + //var poi=self?.wayfindingHelper.spacesWayFinding.getPoIById(id: "44dcc43e-b682-4fff-b8af-999b35f81997") - DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) { - if let poi = self?.wayfindingHelper.spacesWayFinding.getPoIByExternalId(externalId: "44dcc43e-b682-4fff-b8af-999b35f81997") { + /** DispatchQueue.main.asyncAfter(deadline: .now() + 15.0) { + if let poi = self?.wayfindingHelper.spacesWayFinding.getPoIs() { print("POI :") print(poi) - mapWidget.showPoI(poi: poi) { error in + /** mapWidget.showPoI(poi: poi) { error in print("error: POI print(error)") print(error) } - + */ } else { // Handle the case where the PoI was not found print("PoI not found for the given ID.") } } + */ + widget?.highlightPoIByExternalId(externalId: "15-502"){ errror in + + } @@ -89,9 +103,6 @@ class WidgetViewController: UIViewController { - /** mapWidget.showPoI(poi: wayfindingHelper.spacesWayFinding.getPoIById(id: "44dcc43e-b682-4fff-b8af-999b35f81997")!){error in - print(error) - }*/ } diff --git a/SpacesWayFindingSDK-SampleApp-iOS/CustomPathFindingEventsHandler.swift b/SpacesWayFindingSDK-SampleApp-iOS/CustomPathFindingEventsHandler.swift deleted file mode 100644 index b13fc0a..0000000 --- a/SpacesWayFindingSDK-SampleApp-iOS/CustomPathFindingEventsHandler.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// sss.swift -// SpacesWayfindingSample -// -// Created by bhariswa on 29/06/25. -// -import SpacesWayFindingApp - -class CustomPathFindingEventsHandler: PathFindingEventsHandler { - - /// This function is called when the close button is tapped after path finding has finished - - override func pathFindingDidTapClose(_ pathFinding: PathFindingViewController) { - - print("CustomPathFindingEventsHandler: pathFindingDidTapClose") - - // mapWidget.pathFindingEventsHandler?.mapWidget.navigationController?.visibleViewController. - - } - - /// This function is called when the cancel button is tapped while path finding is active. - - override func pathFindingDidTapCancel(_ pathFinding: PathFindingViewController) { - - print("CustomPathFindingEventsHandler: pathFindingDidTapCancel") - // pathFinding.dismiss(animated: true) - - - } - - - /// Function that handles the close action while path finding is still in progress. - - override func handleDidTapCloseWhileInProgress (_ pathFinding: PathFindingViewController) { - //pathFinding.d - print("CustomPathFindingEventsHandler: handleDidTapCloseWhileInProgress") - // mapWidget.pathFindingEventsHandler?.self.handleDidTapCloseWhileInProgress(pathFinding) - - // pathFinding.dismiss(animated: true) - - } - - /// Function that handles the close action when arrived. - - override func handleDidTapCloseWhenArrived() { - - //super.handleDidTapCloseWhenArrived() - print("CustomPathFindingEventsHandler: handleDidTapCloseWhenArrived") - // mapdismiss(animated: true) - - } - -} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/CustomMapEventHandler.swift b/SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomMapEventHandler.swift similarity index 82% rename from SpacesWayFindingSDK-SampleApp-iOS/CustomMapEventHandler.swift rename to SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomMapEventHandler.swift index ffa1721..f5b9d73 100644 --- a/SpacesWayFindingSDK-SampleApp-iOS/CustomMapEventHandler.swift +++ b/SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomMapEventHandler.swift @@ -10,19 +10,29 @@ import Foundation import PointrKit class CustomMapEventHandler: MapEventsHandler { - /// This function is triggered when the map starts loading. + weak var wayfindingHelper: WayfindingHelper? + init(mapWidget: MapWidgetViewController, wayfindingHelper: WayfindingHelper?) { + self.wayfindingHelper = wayfindingHelper + super.init(mapWidget: mapWidget) + } override func mapDidStartLoading(_ map: MapViewController) { print("CustomMapEventHandler: mapDidStartLoading") + } /// This function is triggered when the map finishes loading. override func mapDidEndLoading(_ map: MapViewController) { print("CustomMapEventHandler: mapDidEndLoading") + print("wayfindingHelper.spacesWayFinding.getPoIs()") + //print(self.wayfindingHelper?.spacesWayFinding.getPoIs()) + + addMarkers() - addHeatMap() + // addHeatMap() + } @@ -30,6 +40,12 @@ class CustomMapEventHandler: MapEventsHandler { print("CustomMapEventHandler: mapDidReceiveTap",coordinate) } + + override func map(_ map: MapViewController, didReceiveTapOnFeature: Feature) { + print("CustomMapEventHandler: map",didReceiveTapOnFeature.position.description) + } + + func addHeatMap(){ let geoJSON: [String: Any] = [ @@ -100,9 +116,10 @@ class CustomMapEventHandler: MapEventsHandler { let markerLayer = mapWidget.addMarkerLayer(id: "test-markerLayerId") //markerLayer.setMarkers([ [-122.38749686323516, 37.77017375750313] , [-122.38711522299518, 37.770216437671664]]) - markerLayer.setMarkers([["coordinates": [-122.38711522299518, 37.770216437671664], "name": "Marker 1" ],["coordinates": [-122.38749686323516, 37.77017375750313], "name": "Marker 2" ]]) + markerLayer.setMarkers([["coordinates": [-122.38711522299518, 37.770216437671664], "name": "Marker 1" ,"lvl":1],["coordinates": [-122.38749686323516, 37.77017375750313], "name": "Marker 2","lvl":1 ]]) + - //markerLayer.setIcon(url: "https://wf.ciscospaces.io/wf-api/static/assets/icon.png", imageOptions: [ "pixelRatio": 2, "sdf": true ]) + // markerLayer.setIcon(url: "https://wf.ciscospaces.io/wf-api/static/assets/icon.png", imageOptions: [ "pixelRatio": 2, "sdf": true ]) markerLayer.setPaint(["text-color": "#000000"]) markerLayer.setLayout(["icon-text-fit": "none"]) diff --git a/SpacesWayFindingSDK-SampleApp-iOS/CustomMapExitHandler.swift b/SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomMapExitHandler.swift similarity index 73% rename from SpacesWayFindingSDK-SampleApp-iOS/CustomMapExitHandler.swift rename to SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomMapExitHandler.swift index 8b22f92..d3997e9 100644 --- a/SpacesWayFindingSDK-SampleApp-iOS/CustomMapExitHandler.swift +++ b/SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomMapExitHandler.swift @@ -10,8 +10,7 @@ class CustomMapExitHandler: ExitButtonEventsHandler { /// This function is triggered when the exit button is tapped. - override func exitButtonDidTap(_ exitbutton: MapWidgetExitButton) { - // super.exitButtonDidTap(exitbutton) + override func exitButtonDidTap() { print("CustomMapExitHandler: exitButtonDidTap") } diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomPathFindingEventsHandler.swift b/SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomPathFindingEventsHandler.swift new file mode 100644 index 0000000..6db26ae --- /dev/null +++ b/SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomPathFindingEventsHandler.swift @@ -0,0 +1,32 @@ +// +// sss.swift +// SpacesWayfindingSample +// +// Created by bhariswa on 29/06/25. +// +import SpacesWayFindingApp + +class CustomPathFindingEventsHandler: PathFindingEventsHandler { + + /// This function is called when the close button is tapped after path finding has finished + + override func wayfindingDidTapClose(_ destination: Feature) { + + print("CustomPathFindingEventsHandler: pathFindingDidTapClose") + + // mapWidget.pathFindingEventsHandler?.mapWidget.navigationController?.visibleViewController. + + } + + /// This function is called when the cancel button is tapped while path finding is active. + + override func wayfindingDidTapCancel(_ destination: Feature) { + + print("CustomPathFindingEventsHandler: pathFindingDidTapCancel") + // pathFinding.dismiss(animated: true) + + + } + + +} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Helper/DataResetter.swift b/SpacesWayFindingSDK-SampleApp-iOS/Helper/DataResetter.swift new file mode 100644 index 0000000..3ea8616 --- /dev/null +++ b/SpacesWayFindingSDK-SampleApp-iOS/Helper/DataResetter.swift @@ -0,0 +1,55 @@ +// +// DataResetter.swift +// SpacesWayfindingSample +// +// Created by bhariswa on 21/11/25. +// + +import Foundation +import Security + +struct DataResetter { + static func resetAppData() { + + // 1️⃣ Clear UserDefaults + if let bundleId = Bundle.main.bundleIdentifier { + UserDefaults.standard.removePersistentDomain(forName: bundleId) + UserDefaults.standard.synchronize() + print("🔄 UserDefaults cleared") + } + + // 2️⃣ Clear Keychain Items + let secItemClasses = [ + kSecClassGenericPassword, + kSecClassInternetPassword, + kSecClassCertificate, + kSecClassKey, + kSecClassIdentity + ] + + for secItemClass in secItemClasses { + let query: NSDictionary = [kSecClass: secItemClass] + SecItemDelete(query) + } + print("🔄 Keychain cleared") + + // 3️⃣ Delete Documents, Library, Caches + let fm = FileManager.default + let dirs = [ + fm.urls(for: .documentDirectory, in: .userDomainMask).first, + fm.urls(for: .libraryDirectory, in: .userDomainMask).first, + fm.urls(for: .cachesDirectory, in: .userDomainMask).first + ].compactMap { $0 } + + for url in dirs { + if let items = try? fm.contentsOfDirectory(at: url, includingPropertiesForKeys: nil) { + for item in items { + try? fm.removeItem(at: item) + } + } + } + print("🔄 File system cleared") + + print("✅ All app data reset (DEBUG only)") + } +} From 65c1512e42bb4deaf82a7debc688160f07660902 Mon Sep 17 00:00:00 2001 From: Bandari Hari Swaroop Date: Sat, 21 Mar 2026 10:31:32 +0530 Subject: [PATCH 3/5] Add files via upload --- SpacesWayFindingSDK-SampleApp-iOS.xcodeproj.zip | Bin 0 -> 17398 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 SpacesWayFindingSDK-SampleApp-iOS.xcodeproj.zip diff --git a/SpacesWayFindingSDK-SampleApp-iOS.xcodeproj.zip b/SpacesWayFindingSDK-SampleApp-iOS.xcodeproj.zip new file mode 100644 index 0000000000000000000000000000000000000000..e4d24cbf856ddb5923d6ab80a0e044cd1f23da8b GIT binary patch literal 17398 zcmb_^1#l$0mZh1QnVFfHnVFfHnVH#bW@-Ez zl`3V`Jy%y!=_-{+O0u9}^guvRP(ZvC?t07zwrBJ(KtT1(KtQ}eXh5n?#-`@3n#SG| z)(&RY4wkB7vh=FP_D*)@!cI=~){3eOUZ##_=1wk-HjIBo=B928P9|P|C4qsEfd1og zp`+`XBZU!=5eQx~F*ua^B;c%KU~gY-Jt?S;7;xJWT{~g@+#5r-R*8vc~rj3`dWN@k_^6B>CF0wQxf0t zu)IpHCI4Ym`DkNWnbPMe@vc$k_{GP)A&G~FfBD4)B`kaElMTuuWuigO>{yyU-JrZV zK{1ghuln%?`w3_lyyJzbO)S&Was^ZK$j6YEe_89?hvofP06t_6aRB<~)i#SK!7N$S z?^a-AN(VgK(F&VEBKH;p(;v9<0r8f>m}aLefiY#vKM7Dd6U>X#EQ61}H*H!8A5UZS z3=t#vKdYZvTXO20Td3AnxFhmNK1#@zi0?_~OSQ=E^h02BkavJ`qw;|{kVILH9D*&zgtReP%&e%g{?`L==;z?JeQ$e8c}u$3e~sA zoA%4H681`RJETC(O0VKRb>p!;;hrnNE#u0(h0H4bNmPg5QSn~0%)^BzN%@CPs)_UT zbERFP-BXcPw)(SXVIe^=y+vXqKRFikM!JLwmtvm8!5-mG4-p~m!{(7Mpb`7%Gg0UJ z!PBpq^TR#c__g;@vFDfB%iw4G>1iJYR8I!Nl6}|gl@NaSpB`zia~WeYo$RLc0M`P7 z#a^PFLARf?I*OfKy&XM1fzOwxJeXLJtnD(!$N)3s6sHHaC=~sXrekY{!Ks7=It3EN za%&_7mtVF+=81u}{i_BenebPfd9^WfIS{OZ$-5HJ0=?+li?zr08s}s;m^Oa3>gzKL z+^fG>`QBAg8xDnzXO`wOBcJmFR`u^Qa=;DA7(1HicV;2BC7Mrl)rS#Fobco@qy_rp ziE5b)37d)44Z5;5R~8n}$DD0{7KtWRVIdD2-;}S4$vyS3gL&WmoG#u(M6lf}l+T@T z+j=@X4Rf3C12r6Bxidco&!PRTK{W+iyt`j;Hr_(Rk2Ytz@_MddroH&0!MP{W_o8qX zt|307p|_{VZocIqE#7IsHtSu0l%85Bw947V)$sk^kPJ*%))28^byfy~8B4TpR6L~x}qi-}_QE!n| zhp<*v)rL-OMOEy@-oc;J#6dX<)0I>*XtQqzmWtv=ojozpp&QE=RO2X|W6fKW3b_zH zizTB@v4y)40jKQ^Z2Mk04e4<36hG~qch08SU=Etzy&st2^_4~&fqT*6fMFcNU#2xc zD}VamyCNx=qnIrOZuzSkyk)-8bc-JfOqD7r@+(yHhNzVHRU|+k)~vQG zb4=O!w*-D(>n>$FYgOShxUeD8-T#eZIjEhTQAHU)1Q2Zez(@g8b%RLyWve8-#IDgw z;aBZRMx;%OaKQr3W>rcx;LtdII50-Qrgyx>10)#-SR)M3qvxbFQi74nQZ+Pvq(fj> z2-GHUJ0%?)Z+Fs_ga}w9{ap2KLhk6-(rr%%nXyd{`dHe9jzq>NTg*z6#*^*~pYSk3 zyAHvLP@C-J0w6ZgJ;J~8g8B{-#6h@nmCT6x>e)BTg`?)3+KIuVtwU;UGhBMH+agL6 z>|%(N%(Hnz;+K# zixUCRS_$ntoObZ_;oK-_!j`SSfRh`e$l<1t!6TH0I}J_ImEf2$(VT0np&fNYJ53omTP@tp{?% zq*Kv|lzwKd?rOwGOt_+QcocFji2y0?@6lBWZorqo972S+-x57I0;?pEgIc{!X&M2; zU32*9=-|c_d#z%a6u+)Li^uLy%gX4P=I|orn4*3fgbgbZYw@E_uh_@f$q<>uDHWA;3Ck90FU0V5 zb>E_wSQTOapbhmF*wKep7&-_){%xPvl>+X+x4(6)BwHzC?=d5@+~5WVFO*#Of+4J6 zRV_a{@eTy>p`Tte2)&_F&5j;PtPh6=dt)z2Z+;0pOfzn~xY0w7K_Um-CM+SIeh?-) zU-?L>NghqAg#TSCQhpvtStA8YIpMwqEqhaIrsexYOFlphK>`m(nVc6Wu6kSB7T*M$ z6qsoAQA&QMg}r=-dTPN(2Z`1Ix6Bv<;12u~$lsUG}D_4S*JMnF}#*2Qv9TH+$T{I1`*k;+250l2w zyi=nawc=zwtwr^=jaOd@;kIgCO}3MMf~8Aap{ph(m&bV z_3q+0Q0Z@;sm!-40`o6_GV<%x`fqxsUZ$RoF1D_J`Lv9tjt*|-4sNbr4($KSG&6QH z{%3A$Q^Sw3X=N%|dYYN3*(PZQV;5^zPvftW|9hSpqx#of=`V}8 zSbP~r)y>$={Qur|{VV;?jB?TC?WZdK2+8N#+UzF1P)=)aeIkFW zE4Q(MVwIXwDzuhstf`EQrWpn}uMDE927w`ofl8AXM*{;xOP2>n^A3D0r=}O*_ctUY z{PY?d&7R85;&wgso6TKQkasPaF-wTy0U;s+f~FDzg@6+3Jq>cMnJ;BMjs&xcZz*y6 zt!3&Rv^J-QZ&Zmry__wt05qdhj0_#S_-se3o4GCS2DJ*b0n?&wYk{msOFC6j5ieQl>~GnBtQieUI>L2ilPL=_6xZXoV^fZG1!6$11lK% zTR#{RIv#lov^s64Hqny|QGz82`Lb z9EsbIl?mLu6dSV7fDjw1DKzOHD(2L0;(QW((tP4mlo&{}sEkNIkYb}aiu1G-YKWGR zejuMk-4AUHNtp09gsw`TlM4_(phiY1?8)wt{Xzf3?i|r3dLqS>>`=;kBK(pJDjn#8lqFW445K1#k=$-Zpe=@xYSWloLlK!oI+kn( zuPv)ULYb;MR<&P3M#9V;pQ|uKWSNqfd^=`2_Pj5L$X7$ zL*AOoJC?WayDzyvx-W18=bgbP86cZa$(V#Wel>PAF1wGokA4FIP9=q`CODDMSfNMF zIgxi$*hMW!69!YpQYj}RZLUm1lQU7|QpHD8KvO7FNh2f5FJeuN&z_AV+M@Kk^3Nie z4NG_>_oAs9?vjGLl5CavqKgf9ONx$oZTYg2ZB_iDhYe&)>bk7In7g;lC9ifdmfScfYvPV(3HK7j>zDVSPadTQivFV8!Pq;#vx*JDr z5n)k_8@#^k$~>LEBIjI*75bfg6Z5;yI}abo z?$m(9fP!uDt8&4@$2r1<*JFhj*cY&Oa{mkg$v|1d@*i`WC$@J#?i}I9mEtgePd_n% zVi}GkVvjws0?QGh4u!F>P$Xkdkuht>#f)3Hd;=*DtFnk-63xOX&zNT}$zqNRwl>zu zI+=pApkR&7n&cbj8|0hp8tR&&v*7urK4o+0Zh_g9^BlA`=r?w5E?^>H@xWZb^qQrZ z1v({sh~yf^J)CRNV?4uTndLgwI^}%`d8l~^;hNe${5JB&U<3vd9N%X^gz^OQ1_lcL z5dvgVPo#vThg|4rZN~?P7etB#g6srQr!IaP#cWq?ZI#SZJgK4%vB+T~U+zH!p%5ix z#+w9$DOLneB}597L`gyMUG2nqSDD3J&&$q4&(BLjE{#qPBd;; zBfXz%WU;2!JUwDPgF?d*z;O=!7VJiTjMx>#c?}F2#CQz~iX4wcCd4s@aWCpI7C;UK z6ifsK79zxi1Qx`!AB2~T#7!b;mWY=G6>crI+dff)S6ijDVzijO)*)kW3Tvx^4KFW# z%Cc<6fz`quPv@wguG6GJ>azQ^aB>Fs+g1MiXKHxI@>t_b@>Ug12_SkYYO@n{qJ z$F#0W#d2YZtr16gj$d0{$JQWyhEJyUCnsCu!8%U7l~5fEZTE5w?x+WBv7TCSjUw;^L*_T6RIHMTDA+{lxYY1biZRv!R1;K_!QXr7+TT}) zj*q##J8I)4_Q_-K<75A%4@-zYQ;?1Mm3#$r7wu+86T6xp?sO=^JV|vxp~5Iq5Y$BI zrNH1Qq?G${WMkm%B(3N~KxQE1V<0q0P%cTJE|N59@i9rHG>0QXY1LCIi7au93kg5j zt)?ML$g5s0JCc`d#P+_7AFjPp$$F-xnqD`(mmE8`#|&?=a@l&L^CU0 zz2c0<>_P^+5@Nwz2!28syb?@(4Ai^$V+_`t5mdBKi3tu4k~9f1rPwPiD2033zuFew z-A?SwGKQ83#}1sux;HrUeS*Z)mhy*DBBJ=Vi?(7W>>FdtU)4jvf@FaUPd}XjmnZDF z5cSqsO~dldy`?7lNAl;o{>(ZyMjXUKSs?*ikg`xD1d-u>Bm@JvsSv3Zh-s1_jF|9P z!C9DCnJrtBgux`M4tK`Qnnt{oULku{=h;CDJIM-+|GR(m7QK7DJ9>L}Q_Wj*kaM5= zI11Vvv`)Vm6SN$G4Ku2bJ*uw#^F($8W>q>*Pp6KlE$=t5ay87VSnnniV0FfT#R!Q! zZQFAP&|vGn7I-7JN_aWR{@nKGpDcMoP!^%wznJ64nwFJD`@6zirzch|NNr8-E$BzV zVZ@1tP1*n>rvTxQQmc_sMN$-Y8~MY#b)981le07(R$ehni=3yKL?-umi@Gd(mUy-$ zmp)qNZ*F?&%qN5pFpo7-T)is4h+IN!<>~NL-XB%GXl}Sa-!Zndqzw7` zZl_>D!|ljZ9{@Oy1JL8A@!Hqt@d*?-cRw3w8FV1)J4X~a97moZHk|97p@vHY0Zar! z7V4*jAQ6N!2Q&i0>IK{dh7royM{$j?ir^8f*hlPymJ4#!m-q|k34IeRPzbm=JYf#H zL&)O{?EWbQ%p35Hfv{sI$axdFIGA$Gm9+?S>YPO>% zcku1*HQP1SD-9CyWw^6J&p64h$sP5>Q_0)Il8{~zqEYIv1>lS>QGp0_V6&l^N?b8Q z$y7GfUeH}|2EdHO*fA2!QV)s50n}O+!f&EPp6FVG#GdRi_MktApAAVo@xOs?ztQfG zpvP`^LAHV9dY?o*bd^YO;!=3}n3TXLl=*HX@;9X*w|f}^Y@(HN z;^|usF@6`!s$g{JrB;Qrzf+rHkT?i5u>fGt57eAFpMcJR35(IvViuA@REHD$1q{%C zDvt;j#vm4XOZG7<+$I!HaX8^of2!On1abe`H?%fb4ivft!F9ppuQ_zj+WO4QKKfy$ zalKR1$PGUOV$J&mkt@ti)ry}Bx>L-j)(5{)h=FQL$J}^dGe5TM{%X`kVSjL z+8cnYMQWIlQ_DuOQ%8{Qw4p-5THPx-&FyP+uXAP1mw9U<(|o8*3fqF}Cf^Zlhd-;h zk|gBFg(Q_JLdXU5A|l9!7cWGbY(ae&37ixxe2lD?sAVQ*yaaCNkIB0^P@U81K#kaP zSAhC6iA8^qN?>JOjw|jkJ31(t31%V*W2sO_trZPS1R@s{cnrCL3X$81bhTH-cG3B} z*&fZWWtei73$IBVCDNPoyp1Jm_u8T?++2e!zTkcwz$e z=dIvu&Vz=DfHI0H_Ji)IjKaP;X`Ll=?yI|JEtQH!hU+w%4elL}t1SKoy=P!}17`Lw zB(7pbQBq+dKQMMuNj41dO?-&J;eGG!iAE*FQd(nvyP%RngoFrFBT_pN3Ns0MD?FS; zib4%GXYyVn#C^=Gw@AZ!-kVs@NlH0VnBUF)JibfjICm7FmJnL@!F3~JRh{{$p8A>9 z7$2642OSj4X3HGxkL8H(tS?{QiFaKiXT#lW6s&d=K*4tTfdcVE)j%g_Ez(SPOU2ZN zJ!`Fe`z|?f0x;h<%`Lu8@j&c-#qpDWEE0pW=|#`K9WX)$f|IP8d9tfkw%M21Auehe zRBi7>;d58#F%zr^dgAhg<%cH#d^AA0s|rONS6*~t1(Ds3HxoMB_v}RAhXGcsZN=dO zGc5w!7JO+AKAb_Ap`TiZz@@w3;`{v5KZ*#D@zK7^8smyI#8R7 zMiuL*s`qniJqd@!Z=ym_D@Byg*6=;h zoN5?Vv0p$NyE*!|1b#WF#}apJH0NQuK}Zha8*C(x>lh`;OF6#KLBBz!MQ;=PJa;|X zK%sUOKAL1nQO=&B%gd7wqGF!(X^NtER!yvVA5}>E0`nWLpMf_`*GkTQ z`tiOc=}K&I&Z<0+J~a&IKH_(Jv?bE|eagj4S>emZlRsj;p%DZ@1|t!Kc@B4zPDvble(OER7}D_G|8-t=`4uLh^A^(Ts6RN(cl zIuPi@VHA5b!|_LQ0c~#;oKOqMhI?*3It*z?Jc6|?0{4bd?rI);-?8X~-5?JByv8L8 zv;3v)<#4>UOyeam2YW1jmm;w!*fea$!G>;=(=^iHshxH5)AD)-y{-U8V^`Cj}f zPhx-Ap3H;MXvu=Kb)s2rp2w8;Eg$t6)Vk*F4G7x{p*uvY?zwk6w;rQ&0@L??H})MS z>>8pA+Oa=xum(n3S%YcFj(x=n+D24}G+X0`tr?`GgoKMhI(4H3+L2ZKiUiG?vpC(+ z4=lOlz_o2rB|f1A4DL_hD=V>?iHRHErMf(zT(7IlCFn3P;UqBjw2haBC_H*`e4OM< z!Oemw=-hk`T=)|2OK4zYRyl2LhhZT|W7#`URUZm#u>lnO3oJmwYjPQcC_Ph=R@Y80yGT;k z;v`p)7wCqZ;%e0a{eW(N@d=e6W3Zifg=9PjYZ3>eh?g=k?&NI6N#5x8KcLXxwnWzP zk8w~aZktAS&|e$-^4B|I*w%gRRIZP*S7DhtQgF{i6g#UgrYb{+e>nE4$$x5K(oI)74jd0##cTUG)zCPH?9rk#*ny+YYX!-k>c z3bNUXu^mt8G_6%uTQfJ6=hyHJHr@Q`H32yrUlGawp~zND`JvpywXq~VaBKOZ3SoGN z{ia4b@Y(i@;`l?)LDma^U?ax*K@9MEE&IuNjSJ(M=<(_Th&!seEkM;uud54Y|3ufV z_68(aiK%{21Db2^GrI5q4bK5|wFlZf<;e0cky!S>fH!1N)M6 z@}lI2G>GgeIZ$=yFptG}8{)kn{i7XRS$(?9%LYH=8)mfWr#JOb=Y6xU>)39QzcntHA&5{KIzkwbAlo zk8mijZYhR5m`n;nidQP7R0>C5d}Zz)K}Bdi32I*sq-R4aew;~wBhHhG zvJl=DtSxUXTtdc54d;{JR`Ejiq`>2{HNXWzz1b5DF z)L#lGrI|u(MujaQGw#F^5=T}tM~DRi2MtFJhYe@XbRJpsF2j-?M{Fw1jV(En3T;Lb zk$@#({4LR#KLTq|lW8+*x5!{QL+${6D=#nyQP#r6&lu`cyaznXbT|49vxa|61eWox zcPf%%lFkqMgB<}&+kAKI!SIkTb&%d~?fo?aw{&?Rd$89Ie9au=ObRrqjzYUJ-;PK! zna72VJHn1EM~Xi}1Wp_)hS_ak4qFsDf&r_;8?Ik z(&RY4Xt5Cz!(r|Ert7R1t-C2)k{}%kQE^OdM*iLvX)8a}Fm*Anm+g;(FL+iVC=7R22 z$Ih&g2xG1&TZT$S z#+)l_LwgP<%?1)eAuR_h^;5actNh14|Cbm;&CzA6c;w&huyc9)Hbi7ANk8BjRV166 zk56rMrfaIS$kvnUrI{@i=TqbfKO4MH1-#iKg1cU&dxYz1=~Oh;_Gvc8Is4KST=oxUfbLV?_W$UH3WCB8{w$L1QZ#AizLvb=F?p+CA=ss>ZRwV+MHpzFfRh_Y5 z6wnofiDVQN61a3M3**Yu!dxoL85uLvZ?`+GC~1^PD(|l$Z!0g-D`yK$BpU)ZR*RmO z2)}B;4nV^egL;}-^wq?BJpU}WAl#aX_I|jtMg(gh!da4=XjK;SGYo!7|eg)ME{zz{xVx4JySOb4Q?8S9!tO zRgrz2YzTmKja3cLLBM5T{rju2EP9Bny&7_ax_*6`3?Z2A_iUUIVjC!Sv_WDl1pA5z zRZ=Frh~2SXL;yS5B)iIFzXuoMh7SUO^b%4xt3`=)X{sL(y`TyK$BrcsQUnOak;Ud- zT{hBsWel>XMN&b16=5!6;9xp%S#Ei#M9kCh)4V1|+@KbclE09}Jrn#Kxhu)qSo!2} zU+c%kJRztbUW9|StGKN<|B~WbkN>Bl-apqTA@l-uQSVgxl={@#hTtBKy+B8ZKh_vD zqJ(MDmYYHLQq06f|PGx++}1-oFYK@WZ7Z-!{Cq3Kx+0fe82nUUl(Ys9a%Y z(=qP646ff2vp+y;$yyI7!XC` z$kA`>p5FDSLvK}d|NT(*x%+T6N^cLz&@%skC9oE*tMf#(xlq>(>11EAW#tK1Fydsu zdm;TedW{WN@VSvO+{}m%q{nL|=tFdoxa$XpY4l_Vi7y4|4CRL~82;%Gwy-NCC3z>l z#Hp!|Yp82DcXe-hfw<#!X+s$)qyrJ==4QD5eFr1Ar=^MO<-TBW=Gardzy~w9IalG= zKHjJ|9-|WhWZu}*PhRB3wy`x3maWZdSGYY-9ep)_aJcwT{ zOAe$a?u_&OvDkiX2gI>V+kax!z$p0uZEHSLuDO_1NW7-VcwSa3iYC|8i$La~)?Zk2zb%KoG z)%@w`5$s`#Y1Qgd=sydyuD?~te=Ruo0V&j(33?%k)#C_$L5T=tD82muyKLN7-!+S1ZY#MvV>9n==N1|LoQwEP>;Oy=Lh=1}2!eAov zX5=m<{vG)XBtq*e^V^+a(8k%P@ve8nm%Di6qr7NM^I|8n!q|>V}6~82(5-X&adj64!y60 z4xa&=ETMg6928iCsrqf^0|a5Z6xqq3D;^XP(ZkoaaEdLg&T@Pa70i5}tj3xtk`%Uv&K&sfrPtn#fne=_p5Lrv`7zmi=`pW! z2IPp5Sj7FUQ}5MhAUVn?r~P(%1bF$)uJplJ%H+5mJFwUtI~bZnUFFCl`(pj&F`N2y zY_M2UM(J5YMlT)_sm$qBMi)U>I3k9xBRR@}2MLw?pgyo=R98$ZB0F=2)t8_cT7a2J zE^TC4O~F(IYU7!Wy}-k@sYZjVF=Wm}(JV+<({XR4r_3y1B378X5_V_tr%K>Vm?C)h+J5`Hb3k9QO>t$F3y%x?wAs8r-`HG0mEFU~UdVE;Z{oyH6aD5G^=v zv62AHu1s$&@!oiYxViQ|P}0nbz{Iy~tckwFef%3YN2ZgdUbTbQ6oDgSQHcfP7|KRk;AENpk`PeSVSq0M{HO{*Xk?A!Jk4Y&r1|D zd$u=sr*6tMb;pkIT>pmt4G6CqafgVpn0<;b)@m_74{N(w;~k<2yRFV-ndR);{Z!5r z#3B8my#;9#G%6T{l$_GHLgs!WksxSXxmAb)UzGQOI+NqePnADkh6j2Gp6gvnH^zSPU|-^!sJ~ z+gcE`Ma0gP^r0U`DKba2fHuY@zttlQC?CQS=}+L9Ca@MT7nlw}qt1LwG8! z;U4!3ht`y9GakT4CD=UvT8sg>3wBelWZ`y#4BXFDHix}-8EQDYuCR|+3TW&92xwzM zrkB?z+xYJi6GInP(FrUIne1xm7hC;J8x0o*4 zH7#33yI|ZH*-RpS;OF)h(<(_H=L2b_F3Nfxw^!e8Y-@4n#XFSawe?#CU>0 z>1$Orf(;7^0O6hCaaO#G9R~Av?8^AOLe{pon~aAD#qMA7c$h(9yy_#eHq+b}gOn_i zI$yMx?jRvYU{tB_+*uL@YZTu{a+kHI|3tf}kF74rk^Foe(zbJzRLh|(PL?-M)-j*U zNqmC4cE7_tCREZc)i|SQToOO^Q7-}X4}IB=qv0clC>C#sgM>k&SYjV1d3#D6ZMOtk zZQmu`3=8Ls2NFCoY@1O)S5x$Y*m%o%?XL{UyMzr4f@N+hE}8PLncJ~eUfJZuyz!&_ zk!YBA2oMrTu`u5lICvpiWxtdXn7md^JB_=4;P^R7ZXd}5WI!rGp zKJa&N0}#bvN(vEX|$a02Y{@Ra7sT$_+3w#5+4Oq2VDTb^9C^Us>xi~`zggeu6s_0DC9h~8v%bDfv~L=y}oRd z8)$9G=v?Ya6bxW2R>+qp+4mU^Q##D>%Ro=9QN?N7`*s>4tu`zkhpqwKDx@ehI>A`uGm~)C%8ngrr1wu}Rf0nq9c#L?J_-9d{@DbBU(YSM=X@+UmZ=_M<1X4Wqg!_aNJV{;- zo>P2G9tYRAi9f!hX9>Mr+fH2vPn}5^Fkt`@-l9+?DmWAbjPKz-yQTx-1DN5Au!iUi z$N<1Od}`DWF-9;;TX#N$RSk_U{}DF0z%lPoTUTnddS z)}iOUB9mILX0NU%>OXvc{QflUh3{bwF-99A_tF@UIAAiOJEHc|ZW9M6cFDd4KZ*X4 z-1Fai-viwf-5cDCRj5#$?g{l}T~ilaVbN5Iuf=ovj{a87MbUQTGv zoc#IW`QaJI9DN`C82u{!qWmewZpN|3vBnw4vVF`3N$aq~k9K<}-wpfJ4UE=2hpWyD zkB#4em5b61bI*aTnXP&K{mcE!!^>TPIsPI30sd|Odf!Ih@4f)vc;7tV?pLoz%1z96 zN9UcxkGfZc$Hz@U55bF%+E;tTk-^cy9n$fVxsvUYCDVjaltg#}NInE_ya%pR=gr@) ziKzJq`E~i*`JjC7eDD0A{3ZOVe60LUd`r!6D4 zsVkBOc?PZB&{s}Z{oB;r*4x@5p%G)K~xZU^Lsa+M`v)B0t{G+edSC(Cv zUV=yOU7k6QHdpf78{M8hy;t2Ez6Fl~SD@RGU5LH~w;%JboL4*Dj=np88Xo`LNB>EF z9eSnmgYlE`mw2-B!|~6*^Iku~E&vypedfEmEuNhei1ovGZGLupqPx}JZJMx*pQRKi zc)`0nx#K={-8^zFVD#^~;l6NPKI)nkFOU@weAfHZ&e7*Av>NmVyaY;sUvJWv0SpPD zcLUzz(8IDLx8vNS_`-0f|NFJ$N@wT32iI@sVQas0*fZyD^8^Io+_z*LMZC*wjeF?#nZ>DePAJ`uzk?;sbT_@D(ae%wyVzxMh7g}}lKg;9l-g~x?u z!e^lz5cUY`IL)NT-G%zXgkW3PXxvoZN-u>|!rGxX5a@6;IBG0bLqyX=7lrG>l92wa z$LEEPkor&r7<@FVNPHZtXqzZ}++H?JF!>mKq+X)eoWvf)DM+nIiAf*C3rTHBVM+bO zGbLch9M!|idvE(FE;(~BLWEY-&k+BP<-nqHCuDOM|hN31>Luh^U4jwo8 z0=Nq}eiR?NID}YuTx1Qxa#&o{Wi$?UxNv#c9ApmK^YXML zm@<^FF+=~99-rtw^+gu7G<>0G!FXYJA$fs$VSJ%Vg)WackKSMJrPM9oE!eHfE!?f; z&i#bv1mZ;E1mlEv;bOsm;e7#gL3B5Lw`JGPOZ4gZ`f4B$z8CvL_lXesH%YnVRNOcG zKVGG#W}i}5W5CIvq?uwp1nnFy{`p{8J=Af}+EV3$Bn#Z|>nMOMXUrL!=bB4uW0c4sy<9T{#OkxS@jW;L-G z<-@qunUZ84HBlJJjp0VUwVy&{&NQtXenW93U1rq4w@t`HdG$IkUL|j+Hdz_&!SCev zFg(|6s4(q~eP@4oT;+8UVMyATxHw2~QS^?|qsg3P-Cw)m^DgR=Ghq0Uf|zW(@AFLd z%=ZlPEb{drQgc7{;Nr&oCjEx}hI7C3>y<^{1HwtcWWprRiNvwQaly=jq=K}anA<4X z=$}LKiMr^mf|n{?`hHGbbOIa#0s_neqymCHOg&sZYzFv-$cCspNP;{))Z17)D1yWR zCU3WYbbkxReUg0$`B}dGd1Bn_jr*keh^y8a zEE9zXWtse3W;NA`Xm>KK0Huy%Q@RudJo+6aJbF(|y4cpl$i&UW!^FVE*hIRRr-8*; zYVTT1-b9`xhl|-+X0Ifg%h_kIW@r?pK+2EB*Uvzlp7ewV&WL#857;>*8~a?`Z4d0V-N-VE(i zk2j@Yk})b8q<1lU>)t%M{#F}7#9mbSV^-@KTF3=!%fdg*G(Ty?=|zb zAh+aCVW+iqUzXIyRBN74CfATwtNRZ8-AKJs=6j5icvZ2wHBA|fZh8fcMtT*EnmSF> zsrQn~63vqB_m=OiYPjmUY8z^V)d|%-DtQ`t>Uo;)l^w+$bua4ftiDDb-X5|Ki|3S$ zhSLs{26^4oufNaV*9^@9^WNnj+Rv{V8O=Y_{K+Brx%T0vpr@c`peLipk`IOshmPQ8 zq{o%_)%Mkn;HI(jSy?1=R5MizSZOTf6jT$4EgfdEb3wT^UG!a2UD(@IT`> zQ!8d|XMEWlb+&(c!`>Q9`I0+2Z{KvOd;d77oz^XQ6z}m5@Cwiium~{!NP5fm6a8p@ z%X+@OEtn0Y4pa{C{aAQIf3CjaJPJ(u6#p21Q+>9)>7DNV7D)YB@mBpTc(g<1M1_RT zg)Rl72g?W31@kr9!@j|Sz(Sx?!P>xDVAjyA8ama^)iTx97td*NRXN!ZGvpd@wO+Rm z9KjmW`L#PK@9qt(z^q{QsJB&J=MCV8UtwM{@EMAsN5^i)zF@1#}-BPdR(8!$+}k9#_LjU$ungg(gsw% zFBYk(oGRm};i%Bi$J50##M9R@EM+86FJ<;hlm@80hjhqq)fs#@__6&xK(kx5Tee%$UudgJ;QNQ1 zzlgueyKH-#o=zRL5f!8T0QM= zZsGMLRU+C&-<34sYO$36NQv7IAIFr(9KxuI%MLHbWT7jn)79wcEg7_w+sH1>d`GNK zP|K_1(RJ@R?fg#ook3H-8e++eUDaOK-jKe=<9mi0rAA^+zUsThJ>Ya}>9rcsqjnE^ z@)Ml6Tl3G-$_L@!SulU`$3gyzz7D#7kp=V5I4hw4fo1cT+<%uZ^e@W)ce?vO@P`=x zRZQ9c1+mpnt6Y|BO`jAGP>9yX*gz^D7Yz`#;y>A6mpet&;zm>-8UX{Y$%l z?;~{os47sRz`v&Je Date: Sat, 21 Mar 2026 10:31:53 +0530 Subject: [PATCH 4/5] Delete SpacesWayFindingSDK-SampleApp-iOS directory --- .../AppDelegate.swift | 38 ----- .../AccentColor.colorset/Contents.json | 11 -- .../AppIcon.appiconset/Contents.json | 35 ---- .../Assets.xcassets/Contents.json | 6 - .../Base.lproj/LaunchScreen.storyboard | 25 --- .../Base.lproj/Main.storyboard | 93 ----------- .../Controller/BuildingsViewController.swift | 50 ------ .../Controller/LoadingViewController.swift | 49 ------ .../Controller/WidgetViewController.swift | 152 ------------------ .../Handlers/CustomMapEventHandler.swift | 128 --------------- .../Handlers/CustomMapExitHandler.swift | 17 -- .../CustomPathFindingEventsHandler.swift | 32 ---- .../Helper/DataResetter.swift | 55 ------- .../Helper/WayfindingHelper.swift | 75 --------- SpacesWayFindingSDK-SampleApp-iOS/Info.plist | 37 ----- .../SceneDelegate.swift | 52 ------ 16 files changed, 855 deletions(-) delete mode 100644 SpacesWayFindingSDK-SampleApp-iOS/AppDelegate.swift delete mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/AccentColor.colorset/Contents.json delete mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/Contents.json delete mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Base.lproj/LaunchScreen.storyboard delete mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Base.lproj/Main.storyboard delete mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Controller/BuildingsViewController.swift delete mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Controller/LoadingViewController.swift delete mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Controller/WidgetViewController.swift delete mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomMapEventHandler.swift delete mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomMapExitHandler.swift delete mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomPathFindingEventsHandler.swift delete mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Helper/DataResetter.swift delete mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Helper/WayfindingHelper.swift delete mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Info.plist delete mode 100644 SpacesWayFindingSDK-SampleApp-iOS/SceneDelegate.swift diff --git a/SpacesWayFindingSDK-SampleApp-iOS/AppDelegate.swift b/SpacesWayFindingSDK-SampleApp-iOS/AppDelegate.swift deleted file mode 100644 index efa9bff..0000000 --- a/SpacesWayFindingSDK-SampleApp-iOS/AppDelegate.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// AppDelegate.swift -// SpacesWayfindingSample -// -// Created by Cisco Spaces on 07/02/2025. -// - -import UIKit - -@main -class AppDelegate: UIResponder, UIApplicationDelegate { - - - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - //DataResetter.resetAppData() - // Override point for customization after application launch. - return true - } - - // MARK: UISceneSession Lifecycle - - func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { - - // Called when a new scene session is being created. - // Use this method to select a configuration to create the new scene with. - return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) - } - - func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { - // Called when the user discards a scene session. - // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. - // Use this method to release any resources that were specific to the discarded scenes, as they will not return. - } - - -} - diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/AccentColor.colorset/Contents.json b/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/AccentColor.colorset/Contents.json deleted file mode 100644 index eb87897..0000000 --- a/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/AccentColor.colorset/Contents.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "colors" : [ - { - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 2305880..0000000 --- a/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "platform" : "ios", - "size" : "1024x1024" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "universal", - "platform" : "ios", - "size" : "1024x1024" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "tinted" - } - ], - "idiom" : "universal", - "platform" : "ios", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/Contents.json b/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/Contents.json deleted file mode 100644 index 73c0059..0000000 --- a/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Base.lproj/LaunchScreen.storyboard b/SpacesWayFindingSDK-SampleApp-iOS/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 865e932..0000000 --- a/SpacesWayFindingSDK-SampleApp-iOS/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Base.lproj/Main.storyboard b/SpacesWayFindingSDK-SampleApp-iOS/Base.lproj/Main.storyboard deleted file mode 100644 index 5448544..0000000 --- a/SpacesWayFindingSDK-SampleApp-iOS/Base.lproj/Main.storyboard +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Controller/BuildingsViewController.swift b/SpacesWayFindingSDK-SampleApp-iOS/Controller/BuildingsViewController.swift deleted file mode 100644 index bdf9ee7..0000000 --- a/SpacesWayFindingSDK-SampleApp-iOS/Controller/BuildingsViewController.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// BuildingsViewController.swift -// SpacesWayfindingSample -// -// Created by Cisco Spaces on 07/02/2025. -// - -import UIKit -import SpacesWayFindingApp - -class BuildingsViewController: UITableViewController { - - var buildings: [SpacesBuilding] = [] - var wayfindingHelper = WayfindingHelper() - - - override func viewDidLoad() { - super.viewDidLoad() - navigationItem.title = "Buildings" - } - - override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return buildings.count - } - - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "BuildingCell", for: indexPath) - cell.textLabel?.text = buildings[indexPath.row].name - return cell - } - - override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - tableView.deselectRow(at: indexPath, animated: true) - - let building = buildings[indexPath.row] - let params = SpacesWayFindingParams(building: building) - params.loggerLevel = LoggerLevel.all - presentWidget(buildingParams: params) - } -} - -extension BuildingsViewController { - - func presentWidget(buildingParams: SpacesWayFindingParams) { - let widget = WidgetViewController(buildingParams: buildingParams) - widget.modalPresentationStyle = .fullScreen - navigationController?.present(widget, animated: true) - - } -} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Controller/LoadingViewController.swift b/SpacesWayFindingSDK-SampleApp-iOS/Controller/LoadingViewController.swift deleted file mode 100644 index ce9f26c..0000000 --- a/SpacesWayFindingSDK-SampleApp-iOS/Controller/LoadingViewController.swift +++ /dev/null @@ -1,49 +0,0 @@ -// -// ViewController.swift -// SpacesWayfindingSample -// -// Created by Cisco Spaces on 07/02/2025. -// - -import UIKit -import SpacesWayFindingApp - -class LoadingViewController: UIViewController { - - @IBOutlet weak var loadingSpinner: UIActivityIndicatorView! - @IBOutlet weak var label: UILabel! - - let wayfindingHelper = WayfindingHelper() - - override func viewDidLoad() { - super.viewDidLoad() - loadBuildings() - - } - - func loadBuildings() { - wayfindingHelper.spacesWayFinding.getAllBuildings{ buildings, error in - OperationQueue.main.addOperation { - if let buildingsParams = buildings { - self.presentBuildingsList(buildingsParams: buildingsParams) - } else { - self.loadingSpinner.stopAnimating() - self.label.text = "Error loading buildings" - print(error?.description ?? "No error description") - } - } - } - } - - func presentBuildingsList(buildingsParams: [SpacesBuilding]) { - let storyboard = UIStoryboard(name: "Main", bundle: nil) - let buildingsViewController = storyboard.instantiateViewController(withIdentifier: "BuildingsViewController") as! BuildingsViewController - buildingsViewController.buildings = buildingsParams - - let navigationController = UINavigationController(rootViewController: buildingsViewController) - navigationController.modalPresentationStyle = .fullScreen - - present(navigationController, animated: true) - } -} - diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Controller/WidgetViewController.swift b/SpacesWayFindingSDK-SampleApp-iOS/Controller/WidgetViewController.swift deleted file mode 100644 index 68153e6..0000000 --- a/SpacesWayFindingSDK-SampleApp-iOS/Controller/WidgetViewController.swift +++ /dev/null @@ -1,152 +0,0 @@ -// -// WidgetViewController.swift -// SpacesWayfindingSample -// -// Created by Cisco Spaces on 07/02/2025. -// - -import UIKit -import SpacesWayFindingApp - -class WidgetViewController: UIViewController { - - let wayfindingHelper = WayfindingHelper() - - let buildingParams: SpacesWayFindingParams - - - lazy var spinner: UIActivityIndicatorView = { - let spinner = UIActivityIndicatorView(style: .large) - spinner.color = .white - spinner.hidesWhenStopped = true - return spinner - }() - - init(buildingParams: SpacesWayFindingParams) { - self.buildingParams = buildingParams - super.init(nibName: nil, bundle: nil) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func getPois() -> [PoI]?{ - return self.wayfindingHelper.spacesWayFinding.getPoIs() - } - override func viewDidLoad() { - super.viewDidLoad() - configureViews() - - - wayfindingHelper.getWidget(buildingParams: buildingParams) { [weak self] widget, error in - guard let mapWidget = widget else { - self?.handleError(error) - print("getWidget: error") - print(error) - return - } - - self?.spinner.stopAnimating() - self?.presentMapWidget(mapWidget: mapWidget) - //print(self?.wayfindingHelper.spacesWayFinding.getPoIs()) - - print(self?.wayfindingHelper.spacesWayFinding.getFloors()) - print(self?.wayfindingHelper.spacesWayFinding.getFloor(level: 1)) - //print(self?.wayfindingHelper.spacesWayFinding.getPoIById(id: "44dcc43e-b682-4fff-b8af-999b35f81997")) - //print(self?.wayfindingHelper.spacesWayFinding.getPoIByExternalId(externalId: "1~102A")) - - if let floor = self?.wayfindingHelper.spacesWayFinding.getFloor(level: 3) { - print(self?.wayfindingHelper.spacesWayFinding.getPoIs(floorId: floor.extraData[ "levelExternalIdentifier"] as? String ?? "fasfd")) - - /** mapWidget.showFloor(floor: floor){error in - print("32412erfdserror") - print(error) - }*/ - } - - if let building = self?.wayfindingHelper.spacesWayFinding.getBuildingById(id:self?.buildingParams.building.id ?? "") { - print("buildingafrewrfcasdzcx") - print(building.name) - /** mapWidget.showBuidling(building: building){error in - print("32412erfdserror") - print(error) - }*/ - } - - - //var poi=self?.wayfindingHelper.spacesWayFinding.getPoIById(id: "44dcc43e-b682-4fff-b8af-999b35f81997") - - - /** DispatchQueue.main.asyncAfter(deadline: .now() + 15.0) { - if let poi = self?.wayfindingHelper.spacesWayFinding.getPoIs() { - print("POI :") - print(poi) - /** mapWidget.showPoI(poi: poi) { error in - print("error: POI print(error)") - print(error) - } - */ - } else { - // Handle the case where the PoI was not found - print("PoI not found for the given ID.") - } - } - */ - widget?.highlightPoIByExternalId(externalId: "15-502"){ errror in - - } - - - - } - - - - } - - -} - -extension WidgetViewController { - - func presentMapWidget(mapWidget: MapWidgetViewController) { - addChild(mapWidget) - mapWidget.view.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(mapWidget.view) - mapWidget.didMove(toParent: self) - NSLayoutConstraint.activate([ - mapWidget.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), - mapWidget.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), - mapWidget.view.topAnchor.constraint(equalTo: view.topAnchor), - mapWidget.view.bottomAnchor.constraint(equalTo: view.bottomAnchor) - ]) - } - - func removeMapWidget(mapWidget: MapWidgetViewController) { - mapWidget.willMove(toParent: nil) - mapWidget.view.removeFromSuperview() - mapWidget.removeFromParent() - } -} - -extension WidgetViewController { - - func configureViews() { - view.backgroundColor = .darkGray - view.addSubview(spinner) - spinner.startAnimating() - spinner.ptr_addCenterVerticalConstraint(withConstant: 0) - spinner.ptr_addCenterHorizontalConstraint(withConstant: 0) - } - - func handleError(_ error: Error?) { - spinner.stopAnimating() - let alertController = UIAlertController(title: "Error", message: error?.localizedDescription ?? "Unknown error", preferredStyle: .alert) - let action = UIAlertAction(title: "OK", style: .default) { _ in - self.dismiss(animated: true) - } - alertController.addAction(action) - present(alertController, animated: true) - } -} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomMapEventHandler.swift b/SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomMapEventHandler.swift deleted file mode 100644 index f5b9d73..0000000 --- a/SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomMapEventHandler.swift +++ /dev/null @@ -1,128 +0,0 @@ -// -// CustomMapEventsHandler.swift -// SpacesWayfindingSample -// -// Created by bhariswa on 28/06/25. -// -import UIKit -import SpacesWayFindingApp -import Foundation -import PointrKit - -class CustomMapEventHandler: MapEventsHandler { - /// This function is triggered when the map starts loading. - weak var wayfindingHelper: WayfindingHelper? - - init(mapWidget: MapWidgetViewController, wayfindingHelper: WayfindingHelper?) { - self.wayfindingHelper = wayfindingHelper - super.init(mapWidget: mapWidget) - } - override func mapDidStartLoading(_ map: MapViewController) { - print("CustomMapEventHandler: mapDidStartLoading") - - } - - /// This function is triggered when the map finishes loading. - - override func mapDidEndLoading(_ map: MapViewController) { - print("CustomMapEventHandler: mapDidEndLoading") - print("wayfindingHelper.spacesWayFinding.getPoIs()") - //print(self.wayfindingHelper?.spacesWayFinding.getPoIs()) - - - addMarkers() - // addHeatMap() - - - } - - override func mapDidReceiveTap(_ map: MapViewController, coordinate: CLLocationCoordinate2D) { - print("CustomMapEventHandler: mapDidReceiveTap",coordinate) - } - - - override func map(_ map: MapViewController, didReceiveTapOnFeature: Feature) { - print("CustomMapEventHandler: map",didReceiveTapOnFeature.position.description) - } - - - func addHeatMap(){ - - let geoJSON: [String: Any] = [ - "type": "FeatureCollection", - "features": [ - [ - "type": "Feature", - "properties": [ - "type": "work-space", - "fid": "2", - "name": "heatMap" - ], - "geometry": [ - "type": "Polygon", - "coordinates": [ - [ - [ - -86.5970883661679, - 36.168744183595436 - ], - [ - -86.59718943953625, - 36.168804768473834 - ], - [ - -86.59721967735979, - 36.168739546712104 - ], - [ - -86.5971120088282, - 36.1688297194149 - ] - ] - ] - ] - ] - ] - ] - - guard let geoJSONData = try? JSONSerialization.data(withJSONObject: geoJSON, options: []), - let geoJSONString = String(data: geoJSONData, encoding: .utf8) else { - print("Failed to stringify GeoJSON") - return - } - - mapWidget.addSource(id: "test-sourceId", source: ["type": "geojson", "data": geoJSONString]) - mapWidget.addLayer(layer: [ - "id": "source-layerId123", - "type": "heatmap", - "source": "test-sourceId", - "source-layer": "maps-layer", - "filter":["any", ["==", "type", "work-space"]], - "paint": [ - "fill-color": "#FF0000", - ], - "layout": [ - "text": "{name}", - "text-size": 12, - "icon-image-name": "green_marker", - ], - "minZoom":13, - "maxZoom":20 - ]) - } - - - func addMarkers(){ - - let markerLayer = mapWidget.addMarkerLayer(id: "test-markerLayerId") - //markerLayer.setMarkers([ [-122.38749686323516, 37.77017375750313] , [-122.38711522299518, 37.770216437671664]]) - markerLayer.setMarkers([["coordinates": [-122.38711522299518, 37.770216437671664], "name": "Marker 1" ,"lvl":1],["coordinates": [-122.38749686323516, 37.77017375750313], "name": "Marker 2","lvl":1 ]]) - - - // markerLayer.setIcon(url: "https://wf.ciscospaces.io/wf-api/static/assets/icon.png", imageOptions: [ "pixelRatio": 2, "sdf": true ]) - - markerLayer.setPaint(["text-color": "#000000"]) - markerLayer.setLayout(["icon-text-fit": "none"]) - } - -} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomMapExitHandler.swift b/SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomMapExitHandler.swift deleted file mode 100644 index d3997e9..0000000 --- a/SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomMapExitHandler.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// MapExitHandler.swift -// SpacesWayfindingSample -// -// Created by bhariswa on 29/06/25. -// -import SpacesWayFindingApp - -class CustomMapExitHandler: ExitButtonEventsHandler { - - /// This function is triggered when the exit button is tapped. - - override func exitButtonDidTap() { - print("CustomMapExitHandler: exitButtonDidTap") - } - -} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomPathFindingEventsHandler.swift b/SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomPathFindingEventsHandler.swift deleted file mode 100644 index 6db26ae..0000000 --- a/SpacesWayFindingSDK-SampleApp-iOS/Handlers/CustomPathFindingEventsHandler.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// sss.swift -// SpacesWayfindingSample -// -// Created by bhariswa on 29/06/25. -// -import SpacesWayFindingApp - -class CustomPathFindingEventsHandler: PathFindingEventsHandler { - - /// This function is called when the close button is tapped after path finding has finished - - override func wayfindingDidTapClose(_ destination: Feature) { - - print("CustomPathFindingEventsHandler: pathFindingDidTapClose") - - // mapWidget.pathFindingEventsHandler?.mapWidget.navigationController?.visibleViewController. - - } - - /// This function is called when the cancel button is tapped while path finding is active. - - override func wayfindingDidTapCancel(_ destination: Feature) { - - print("CustomPathFindingEventsHandler: pathFindingDidTapCancel") - // pathFinding.dismiss(animated: true) - - - } - - -} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Helper/DataResetter.swift b/SpacesWayFindingSDK-SampleApp-iOS/Helper/DataResetter.swift deleted file mode 100644 index 3ea8616..0000000 --- a/SpacesWayFindingSDK-SampleApp-iOS/Helper/DataResetter.swift +++ /dev/null @@ -1,55 +0,0 @@ -// -// DataResetter.swift -// SpacesWayfindingSample -// -// Created by bhariswa on 21/11/25. -// - -import Foundation -import Security - -struct DataResetter { - static func resetAppData() { - - // 1️⃣ Clear UserDefaults - if let bundleId = Bundle.main.bundleIdentifier { - UserDefaults.standard.removePersistentDomain(forName: bundleId) - UserDefaults.standard.synchronize() - print("🔄 UserDefaults cleared") - } - - // 2️⃣ Clear Keychain Items - let secItemClasses = [ - kSecClassGenericPassword, - kSecClassInternetPassword, - kSecClassCertificate, - kSecClassKey, - kSecClassIdentity - ] - - for secItemClass in secItemClasses { - let query: NSDictionary = [kSecClass: secItemClass] - SecItemDelete(query) - } - print("🔄 Keychain cleared") - - // 3️⃣ Delete Documents, Library, Caches - let fm = FileManager.default - let dirs = [ - fm.urls(for: .documentDirectory, in: .userDomainMask).first, - fm.urls(for: .libraryDirectory, in: .userDomainMask).first, - fm.urls(for: .cachesDirectory, in: .userDomainMask).first - ].compactMap { $0 } - - for url in dirs { - if let items = try? fm.contentsOfDirectory(at: url, includingPropertiesForKeys: nil) { - for item in items { - try? fm.removeItem(at: item) - } - } - } - print("🔄 File system cleared") - - print("✅ All app data reset (DEBUG only)") - } -} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Helper/WayfindingHelper.swift b/SpacesWayFindingSDK-SampleApp-iOS/Helper/WayfindingHelper.swift deleted file mode 100644 index ca73b60..0000000 --- a/SpacesWayFindingSDK-SampleApp-iOS/Helper/WayfindingHelper.swift +++ /dev/null @@ -1,75 +0,0 @@ -// -// WayfindingHelper.swift -// SpacesWayfindingSample -// -// Created by Cisco Spaces on 07/02/2025. -// - -import UIKit -import SpacesWayFindingApp - -class WayfindingHelper: NSObject { - - let spacesWayFinding = SpacesWayFinding(apiKey:,region: ) - - - - private var completion: ((MapWidgetViewController?, Error?) -> Void)? - - func getWidget(buildingParams: SpacesWayFindingParams, completion: ((MapWidgetViewController?, Error?) -> Void)? = nil) { - - self.completion = completion - - spacesWayFinding.selectBuilding(params: buildingParams) { [weak self] (state) in - switch state { - case .running: - print("Wayfinding is running") - self?.handleCompletion(error: nil) - break; - case .failedNoInternetConnection: - print("Failed: No internet") - case .failedValidation: - print("Validation failed") - case .off: - print("off") - // removeMapWidget(mapWidget: MapWidgetTheme) - default: - print("Current state: \(state)") - } - - } - - } -} - -extension WayfindingHelper { - - func handleCompletion(error: Error?) { - OperationQueue.main.addOperation { [weak self] in - if let error = error { - self?.completion?(nil, error) - return - } - - - let config = MapWidgetConfiguration.defaultConfiguration() - config.isJoystickEnabled = true - config.animationType=MapAnimationType.flyOver - config.minimumZoomLevel=12 - config.maximumZoomLevel=24 - - - let theme = MapWidgetTheme(accentColor: "000000", backgroundColor: "000000", foregroundColor: "000000", successColor: "FFFFFF", alertColor: "FFFFFF", dangerColor: "FFFFFF", infoColor: "FFFFFF") - - config.theme = theme - let mapWidget = MapWidgetViewController(configuration: config) - - mapWidget.mapEventsHandler = CustomMapEventHandler(mapWidget: mapWidget, wayfindingHelper: self) - mapWidget.pathFindingEventsHandler = CustomPathFindingEventsHandler(mapWidget: mapWidget) - mapWidget.mapExitHandler = CustomMapExitHandler(mapWidget: mapWidget) - - self?.completion?(mapWidget, nil) - self?.completion = nil - } - } -} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Info.plist b/SpacesWayFindingSDK-SampleApp-iOS/Info.plist deleted file mode 100644 index 20d4b10..0000000 --- a/SpacesWayFindingSDK-SampleApp-iOS/Info.plist +++ /dev/null @@ -1,37 +0,0 @@ - - - - - NSMotionUsageDescription - Motion data required to enhance wayfinding experience across multiple levels - NSCameraUsageDescription - Camera access is required for scanning QR codes. - NSLocationWhenInUseUsageDescription - Turn-by-turn navigation and location-based notifications require location services to be enabled - NSLocationAlwaysUsageDescription - Turn-by-turn navigation and location-based notifications require location services to be enabled - NSLocationAlwaysAndWhenInUseUsageDescription - Turn-by-turn navigation and location-based notifications require location services to be enabled - NSBluetoothAlwaysUsageDescription - Bluetooth permission is required to remind you to turn your Bluetooth on - UIApplicationSceneManifest - - UIApplicationSupportsMultipleScenes - - UISceneConfigurations - - UIWindowSceneSessionRoleApplication - - - UISceneConfigurationName - Default Configuration - UISceneDelegateClassName - $(PRODUCT_MODULE_NAME).SceneDelegate - UISceneStoryboardFile - Main - - - - - - diff --git a/SpacesWayFindingSDK-SampleApp-iOS/SceneDelegate.swift b/SpacesWayFindingSDK-SampleApp-iOS/SceneDelegate.swift deleted file mode 100644 index d791a0c..0000000 --- a/SpacesWayFindingSDK-SampleApp-iOS/SceneDelegate.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// SceneDelegate.swift -// SpacesWayfindingSample -// -// Created by Cisco Spaces on 07/02/2025. -// - -import UIKit - -class SceneDelegate: UIResponder, UIWindowSceneDelegate { - - var window: UIWindow? - - - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { - // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. - // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. - // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). - guard let _ = (scene as? UIWindowScene) else { return } - } - - func sceneDidDisconnect(_ scene: UIScene) { - // Called as the scene is being released by the system. - // This occurs shortly after the scene enters the background, or when its session is discarded. - // Release any resources associated with this scene that can be re-created the next time the scene connects. - // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). - } - - func sceneDidBecomeActive(_ scene: UIScene) { - // Called when the scene has moved from an inactive state to an active state. - // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. - } - - func sceneWillResignActive(_ scene: UIScene) { - // Called when the scene will move from an active state to an inactive state. - // This may occur due to temporary interruptions (ex. an incoming phone call). - } - - func sceneWillEnterForeground(_ scene: UIScene) { - // Called as the scene transitions from the background to the foreground. - // Use this method to undo the changes made on entering the background. - } - - func sceneDidEnterBackground(_ scene: UIScene) { - // Called as the scene transitions from the foreground to the background. - // Use this method to save data, release shared resources, and store enough scene-specific state information - // to restore the scene back to its current state. - } - - -} - From 257160faccf14f2288a6eb451a78dd235b3cde9e Mon Sep 17 00:00:00 2001 From: Bandari Hari Swaroop Date: Sat, 21 Mar 2026 10:32:27 +0530 Subject: [PATCH 5/5] Add files via upload --- .../AppDelegate.swift | 36 +++++ .../AccentColor.colorset/Contents.json | 11 ++ .../AppIcon.appiconset/Contents.json | 35 +++++ .../Assets.xcassets/Contents.json | 6 + .../Base.lproj/LaunchScreen.storyboard | 25 ++++ .../Base.lproj/Main.storyboard | 93 ++++++++++++ .../BuildingsViewController.swift | 49 ++++++ .../CustomMapEventHandler.swift | 111 ++++++++++++++ .../CustomMapExitHandler.swift | 18 +++ .../CustomPathFindingEventsHandler.swift | 53 +++++++ SpacesWayFindingSDK-SampleApp-iOS/Info.plist | 37 +++++ .../LoadingViewController.swift | 49 ++++++ .../SceneDelegate.swift | 52 +++++++ .../WidgetViewController.swift | 141 ++++++++++++++++++ 14 files changed, 716 insertions(+) create mode 100644 SpacesWayFindingSDK-SampleApp-iOS/AppDelegate.swift create mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/Contents.json create mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Base.lproj/LaunchScreen.storyboard create mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Base.lproj/Main.storyboard create mode 100644 SpacesWayFindingSDK-SampleApp-iOS/BuildingsViewController.swift create mode 100644 SpacesWayFindingSDK-SampleApp-iOS/CustomMapEventHandler.swift create mode 100644 SpacesWayFindingSDK-SampleApp-iOS/CustomMapExitHandler.swift create mode 100644 SpacesWayFindingSDK-SampleApp-iOS/CustomPathFindingEventsHandler.swift create mode 100644 SpacesWayFindingSDK-SampleApp-iOS/Info.plist create mode 100644 SpacesWayFindingSDK-SampleApp-iOS/LoadingViewController.swift create mode 100644 SpacesWayFindingSDK-SampleApp-iOS/SceneDelegate.swift create mode 100644 SpacesWayFindingSDK-SampleApp-iOS/WidgetViewController.swift diff --git a/SpacesWayFindingSDK-SampleApp-iOS/AppDelegate.swift b/SpacesWayFindingSDK-SampleApp-iOS/AppDelegate.swift new file mode 100644 index 0000000..b64a4a9 --- /dev/null +++ b/SpacesWayFindingSDK-SampleApp-iOS/AppDelegate.swift @@ -0,0 +1,36 @@ +// +// AppDelegate.swift +// SpacesWayfindingSample +// +// Created by Cisco Spaces on 07/02/2025. +// + +import UIKit + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. + } + + +} + diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/AccentColor.colorset/Contents.json b/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2305880 --- /dev/null +++ b/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,35 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/Contents.json b/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/SpacesWayFindingSDK-SampleApp-iOS/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Base.lproj/LaunchScreen.storyboard b/SpacesWayFindingSDK-SampleApp-iOS/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..865e932 --- /dev/null +++ b/SpacesWayFindingSDK-SampleApp-iOS/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Base.lproj/Main.storyboard b/SpacesWayFindingSDK-SampleApp-iOS/Base.lproj/Main.storyboard new file mode 100644 index 0000000..5448544 --- /dev/null +++ b/SpacesWayFindingSDK-SampleApp-iOS/Base.lproj/Main.storyboard @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SpacesWayFindingSDK-SampleApp-iOS/BuildingsViewController.swift b/SpacesWayFindingSDK-SampleApp-iOS/BuildingsViewController.swift new file mode 100644 index 0000000..d75449d --- /dev/null +++ b/SpacesWayFindingSDK-SampleApp-iOS/BuildingsViewController.swift @@ -0,0 +1,49 @@ +// +// BuildingsViewController.swift +// SpacesWayfindingSample +// +// Created by Cisco Spaces on 07/02/2025. +// + +import UIKit +import SpacesWayFindingApp + +class BuildingsViewController: UITableViewController { + + var buildings: [SpacesBuilding] = [] + var wayfindingHelper = WayfindingHelper() + + + override func viewDidLoad() { + super.viewDidLoad() + navigationItem.title = "Buildings" + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return buildings.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "BuildingCell", for: indexPath) + cell.textLabel?.text = buildings[indexPath.row].name + return cell + } + + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + + let building = buildings[indexPath.row] + let params = SpacesWayFindingParams(building: building) + presentWidget(buildingParams: params) + } +} + +extension BuildingsViewController { + + func presentWidget(buildingParams: SpacesWayFindingParams) { + + let widget = WidgetViewController(buildingParams: buildingParams) + widget.modalPresentationStyle = .fullScreen + navigationController?.present(widget, animated: true) + } +} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/CustomMapEventHandler.swift b/SpacesWayFindingSDK-SampleApp-iOS/CustomMapEventHandler.swift new file mode 100644 index 0000000..ffa1721 --- /dev/null +++ b/SpacesWayFindingSDK-SampleApp-iOS/CustomMapEventHandler.swift @@ -0,0 +1,111 @@ +// +// CustomMapEventsHandler.swift +// SpacesWayfindingSample +// +// Created by bhariswa on 28/06/25. +// +import UIKit +import SpacesWayFindingApp +import Foundation +import PointrKit + +class CustomMapEventHandler: MapEventsHandler { + + /// This function is triggered when the map starts loading. + + override func mapDidStartLoading(_ map: MapViewController) { + print("CustomMapEventHandler: mapDidStartLoading") + } + + /// This function is triggered when the map finishes loading. + + override func mapDidEndLoading(_ map: MapViewController) { + print("CustomMapEventHandler: mapDidEndLoading") + addMarkers() + addHeatMap() + + } + + override func mapDidReceiveTap(_ map: MapViewController, coordinate: CLLocationCoordinate2D) { + print("CustomMapEventHandler: mapDidReceiveTap",coordinate) + } + + func addHeatMap(){ + + let geoJSON: [String: Any] = [ + "type": "FeatureCollection", + "features": [ + [ + "type": "Feature", + "properties": [ + "type": "work-space", + "fid": "2", + "name": "heatMap" + ], + "geometry": [ + "type": "Polygon", + "coordinates": [ + [ + [ + -86.5970883661679, + 36.168744183595436 + ], + [ + -86.59718943953625, + 36.168804768473834 + ], + [ + -86.59721967735979, + 36.168739546712104 + ], + [ + -86.5971120088282, + 36.1688297194149 + ] + ] + ] + ] + ] + ] + ] + + guard let geoJSONData = try? JSONSerialization.data(withJSONObject: geoJSON, options: []), + let geoJSONString = String(data: geoJSONData, encoding: .utf8) else { + print("Failed to stringify GeoJSON") + return + } + + mapWidget.addSource(id: "test-sourceId", source: ["type": "geojson", "data": geoJSONString]) + mapWidget.addLayer(layer: [ + "id": "source-layerId123", + "type": "heatmap", + "source": "test-sourceId", + "source-layer": "maps-layer", + "filter":["any", ["==", "type", "work-space"]], + "paint": [ + "fill-color": "#FF0000", + ], + "layout": [ + "text": "{name}", + "text-size": 12, + "icon-image-name": "green_marker", + ], + "minZoom":13, + "maxZoom":20 + ]) + } + + + func addMarkers(){ + + let markerLayer = mapWidget.addMarkerLayer(id: "test-markerLayerId") + //markerLayer.setMarkers([ [-122.38749686323516, 37.77017375750313] , [-122.38711522299518, 37.770216437671664]]) + markerLayer.setMarkers([["coordinates": [-122.38711522299518, 37.770216437671664], "name": "Marker 1" ],["coordinates": [-122.38749686323516, 37.77017375750313], "name": "Marker 2" ]]) + + //markerLayer.setIcon(url: "https://wf.ciscospaces.io/wf-api/static/assets/icon.png", imageOptions: [ "pixelRatio": 2, "sdf": true ]) + + markerLayer.setPaint(["text-color": "#000000"]) + markerLayer.setLayout(["icon-text-fit": "none"]) + } + +} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/CustomMapExitHandler.swift b/SpacesWayFindingSDK-SampleApp-iOS/CustomMapExitHandler.swift new file mode 100644 index 0000000..8b22f92 --- /dev/null +++ b/SpacesWayFindingSDK-SampleApp-iOS/CustomMapExitHandler.swift @@ -0,0 +1,18 @@ +// +// MapExitHandler.swift +// SpacesWayfindingSample +// +// Created by bhariswa on 29/06/25. +// +import SpacesWayFindingApp + +class CustomMapExitHandler: ExitButtonEventsHandler { + + /// This function is triggered when the exit button is tapped. + + override func exitButtonDidTap(_ exitbutton: MapWidgetExitButton) { + // super.exitButtonDidTap(exitbutton) + print("CustomMapExitHandler: exitButtonDidTap") + } + +} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/CustomPathFindingEventsHandler.swift b/SpacesWayFindingSDK-SampleApp-iOS/CustomPathFindingEventsHandler.swift new file mode 100644 index 0000000..b13fc0a --- /dev/null +++ b/SpacesWayFindingSDK-SampleApp-iOS/CustomPathFindingEventsHandler.swift @@ -0,0 +1,53 @@ +// +// sss.swift +// SpacesWayfindingSample +// +// Created by bhariswa on 29/06/25. +// +import SpacesWayFindingApp + +class CustomPathFindingEventsHandler: PathFindingEventsHandler { + + /// This function is called when the close button is tapped after path finding has finished + + override func pathFindingDidTapClose(_ pathFinding: PathFindingViewController) { + + print("CustomPathFindingEventsHandler: pathFindingDidTapClose") + + // mapWidget.pathFindingEventsHandler?.mapWidget.navigationController?.visibleViewController. + + } + + /// This function is called when the cancel button is tapped while path finding is active. + + override func pathFindingDidTapCancel(_ pathFinding: PathFindingViewController) { + + print("CustomPathFindingEventsHandler: pathFindingDidTapCancel") + // pathFinding.dismiss(animated: true) + + + } + + + /// Function that handles the close action while path finding is still in progress. + + override func handleDidTapCloseWhileInProgress (_ pathFinding: PathFindingViewController) { + //pathFinding.d + print("CustomPathFindingEventsHandler: handleDidTapCloseWhileInProgress") + // mapWidget.pathFindingEventsHandler?.self.handleDidTapCloseWhileInProgress(pathFinding) + + // pathFinding.dismiss(animated: true) + + } + + /// Function that handles the close action when arrived. + + override func handleDidTapCloseWhenArrived() { + + //super.handleDidTapCloseWhenArrived() + print("CustomPathFindingEventsHandler: handleDidTapCloseWhenArrived") + // mapdismiss(animated: true) + + } + +} diff --git a/SpacesWayFindingSDK-SampleApp-iOS/Info.plist b/SpacesWayFindingSDK-SampleApp-iOS/Info.plist new file mode 100644 index 0000000..20d4b10 --- /dev/null +++ b/SpacesWayFindingSDK-SampleApp-iOS/Info.plist @@ -0,0 +1,37 @@ + + + + + NSMotionUsageDescription + Motion data required to enhance wayfinding experience across multiple levels + NSCameraUsageDescription + Camera access is required for scanning QR codes. + NSLocationWhenInUseUsageDescription + Turn-by-turn navigation and location-based notifications require location services to be enabled + NSLocationAlwaysUsageDescription + Turn-by-turn navigation and location-based notifications require location services to be enabled + NSLocationAlwaysAndWhenInUseUsageDescription + Turn-by-turn navigation and location-based notifications require location services to be enabled + NSBluetoothAlwaysUsageDescription + Bluetooth permission is required to remind you to turn your Bluetooth on + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + + diff --git a/SpacesWayFindingSDK-SampleApp-iOS/LoadingViewController.swift b/SpacesWayFindingSDK-SampleApp-iOS/LoadingViewController.swift new file mode 100644 index 0000000..ce9f26c --- /dev/null +++ b/SpacesWayFindingSDK-SampleApp-iOS/LoadingViewController.swift @@ -0,0 +1,49 @@ +// +// ViewController.swift +// SpacesWayfindingSample +// +// Created by Cisco Spaces on 07/02/2025. +// + +import UIKit +import SpacesWayFindingApp + +class LoadingViewController: UIViewController { + + @IBOutlet weak var loadingSpinner: UIActivityIndicatorView! + @IBOutlet weak var label: UILabel! + + let wayfindingHelper = WayfindingHelper() + + override func viewDidLoad() { + super.viewDidLoad() + loadBuildings() + + } + + func loadBuildings() { + wayfindingHelper.spacesWayFinding.getAllBuildings{ buildings, error in + OperationQueue.main.addOperation { + if let buildingsParams = buildings { + self.presentBuildingsList(buildingsParams: buildingsParams) + } else { + self.loadingSpinner.stopAnimating() + self.label.text = "Error loading buildings" + print(error?.description ?? "No error description") + } + } + } + } + + func presentBuildingsList(buildingsParams: [SpacesBuilding]) { + let storyboard = UIStoryboard(name: "Main", bundle: nil) + let buildingsViewController = storyboard.instantiateViewController(withIdentifier: "BuildingsViewController") as! BuildingsViewController + buildingsViewController.buildings = buildingsParams + + let navigationController = UINavigationController(rootViewController: buildingsViewController) + navigationController.modalPresentationStyle = .fullScreen + + present(navigationController, animated: true) + } +} + diff --git a/SpacesWayFindingSDK-SampleApp-iOS/SceneDelegate.swift b/SpacesWayFindingSDK-SampleApp-iOS/SceneDelegate.swift new file mode 100644 index 0000000..d791a0c --- /dev/null +++ b/SpacesWayFindingSDK-SampleApp-iOS/SceneDelegate.swift @@ -0,0 +1,52 @@ +// +// SceneDelegate.swift +// SpacesWayfindingSample +// +// Created by Cisco Spaces on 07/02/2025. +// + +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). + guard let _ = (scene as? UIWindowScene) else { return } + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } + + +} + diff --git a/SpacesWayFindingSDK-SampleApp-iOS/WidgetViewController.swift b/SpacesWayFindingSDK-SampleApp-iOS/WidgetViewController.swift new file mode 100644 index 0000000..32cf982 --- /dev/null +++ b/SpacesWayFindingSDK-SampleApp-iOS/WidgetViewController.swift @@ -0,0 +1,141 @@ +// +// WidgetViewController.swift +// SpacesWayfindingSample +// +// Created by Cisco Spaces on 07/02/2025. +// + +import UIKit +import SpacesWayFindingApp + +class WidgetViewController: UIViewController { + + let wayfindingHelper = WayfindingHelper() + + let buildingParams: SpacesWayFindingParams + + + lazy var spinner: UIActivityIndicatorView = { + let spinner = UIActivityIndicatorView(style: .large) + spinner.color = .white + spinner.hidesWhenStopped = true + return spinner + }() + + init(buildingParams: SpacesWayFindingParams) { + self.buildingParams = buildingParams + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + configureViews() + + + wayfindingHelper.getWidget(buildingParams: buildingParams) { [weak self] widget, error in + guard let mapWidget = widget else { + self?.handleError(error) + print("getWidget: error") + print(error) + return + } + + + self?.spinner.stopAnimating() + self?.presentMapWidget(mapWidget: mapWidget) + print(self?.wayfindingHelper.spacesWayFinding.getPoIs()) + if let poi = self?.wayfindingHelper.spacesWayFinding.getPoIs().first { + // print(poi) // Will print your custom content + } + print(self?.wayfindingHelper.spacesWayFinding.getFloors()) + print(self?.wayfindingHelper.spacesWayFinding.getFloor(level: 1)) + //print(self?.wayfindingHelper.spacesWayFinding.getPoIById(id: "44dcc43e-b682-4fff-b8af-999b35f81997")) + //print(self?.wayfindingHelper.spacesWayFinding.getPoIByExternalId(externalId: "1~102A")) + + if let floor = self?.wayfindingHelper.spacesWayFinding.getFloor(level: 3) { + print(self?.wayfindingHelper.spacesWayFinding.getPoIs(floorId: floor.extraData[ "levelExternalIdentifier"] as? String ?? "fasfd")) + + mapWidget.showFloor(floor: floor){error in + print("32412erfdserror") + print(error) + } + } + + var poi=self?.wayfindingHelper.spacesWayFinding.getPoIById(id: "44dcc43e-b682-4fff-b8af-999b35f81997") + + + DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) { + if let poi = self?.wayfindingHelper.spacesWayFinding.getPoIByExternalId(externalId: "44dcc43e-b682-4fff-b8af-999b35f81997") { + print("POI :") + print(poi) + mapWidget.showPoI(poi: poi) { error in + print("error: POI print(error)") + print(error) + } + + } else { + // Handle the case where the PoI was not found + print("PoI not found for the given ID.") + } + } + + + + } + + + + /** mapWidget.showPoI(poi: wayfindingHelper.spacesWayFinding.getPoIById(id: "44dcc43e-b682-4fff-b8af-999b35f81997")!){error in + print(error) + }*/ + } + + +} + +extension WidgetViewController { + + func presentMapWidget(mapWidget: MapWidgetViewController) { + addChild(mapWidget) + mapWidget.view.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(mapWidget.view) + mapWidget.didMove(toParent: self) + NSLayoutConstraint.activate([ + mapWidget.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), + mapWidget.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), + mapWidget.view.topAnchor.constraint(equalTo: view.topAnchor), + mapWidget.view.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + + func removeMapWidget(mapWidget: MapWidgetViewController) { + mapWidget.willMove(toParent: nil) + mapWidget.view.removeFromSuperview() + mapWidget.removeFromParent() + } +} + +extension WidgetViewController { + + func configureViews() { + view.backgroundColor = .darkGray + view.addSubview(spinner) + spinner.startAnimating() + spinner.ptr_addCenterVerticalConstraint(withConstant: 0) + spinner.ptr_addCenterHorizontalConstraint(withConstant: 0) + } + + func handleError(_ error: Error?) { + spinner.stopAnimating() + let alertController = UIAlertController(title: "Error", message: error?.localizedDescription ?? "Unknown error", preferredStyle: .alert) + let action = UIAlertAction(title: "OK", style: .default) { _ in + self.dismiss(animated: true) + } + alertController.addAction(action) + present(alertController, animated: true) + } +}