// // BlueGpsView.swift // Runner // // Created by Penguin. // import Foundation import UIKit import Flutter import PenNavUI import PenguinINRenderer import Foundation import Flutter import UIKit /** * A custom Flutter platform view for displaying Penguin UI components. * This class integrates with the Penguin navigation SDK and handles UI events. */ class PenguinView: NSObject, FlutterPlatformView, PIEventsDelegate, PenNavInitializationDelegate { // The main view displayed within the platform view private var _view: UIView private var model: PenguinModel? private var methodChannel: FlutterMethodChannel var onSuccess: (() -> Void)? /** * Initializes the PenguinView with the provided parameters. * * @param frame The frame of the view, specifying its size and position. * @param viewId A unique identifier for this view instance. * @param args Optional arguments provided for creating the view. * @param messenger The [FlutterBinaryMessenger] used for communication with Dart. */ init( frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?, binaryMessenger messenger: FlutterBinaryMessenger? ) { _view = UIView() methodChannel = FlutterMethodChannel(name: "launch_penguin_ui", binaryMessenger: messenger!) super.init() // Get the screen's width and height to set the view's frame let screenWidth = UIScreen.main.bounds.width let screenHeight = UIScreen.main.bounds.height // Uncomment to set the background color of the view // _view.backgroundColor = UIColor.red // Set the frame of the view to cover the entire screen _view.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight) print("========Inside Penguin View ========") print(args) guard let arguments = args as? [String: Any] else { print("Error: Arguments are not in the expected format.") return } print("===== i got tha Args=======") // Initialize the model from the arguments if let penguinModel = PenguinModel(from: arguments) { self.model = penguinModel initPenguin(args: penguinModel) } else { print("Error: Failed to initialize PenguinModel from arguments ") } // Initialize the Penguin SDK with required configurations // initPenguin( arguments: args) } /** * Initializes the Penguin SDK with custom configuration settings. */ func initPenguin(args: PenguinModel) { // Set the initialization delegate to handle SDK initialization events PenNavUIManager.shared.initializationDelegate = self // Configure the Penguin SDK with necessary parameters PIRendererSettings.styleUri = "mapbox://styles/rwaid/cm3h30b36007v01qz7ik8a0sk" PenNavUIManager.shared .setClientKey(args.clientKey) .setClientID(args.clientID) .setUsername(args.username) .setSimulationModeEnabled(isEnable: args.isSimulationModeEnabled) .setBaseURL(dataURL: args.dataURL, positionURL: args.positionURL) .setServiceName(dataServiceName: args.dataServiceName, positionServiceName: args.positionServiceName) .setIsShowUserName(args.isShowUserName) .setIsUpdateUserLocationSmoothly(args.isUpdateUserLocationSmoothly) .setEnableReportIssue(enable: args.isEnableReportIssue) .setLanguage(args.languageCode) .setBackButtonVisibility(visible: true) .setCampusID(args.projectID) .build() } /** * Returns the main view associated with this platform view. * * @return The UIView instance that represents this platform view. */ func view() -> UIView { return _view } // MARK: - PIEventsDelegate Methods /** * Called when the Penguin UI is dismissed. */ func onPenNavUIDismiss() { // Handle UI dismissal if needed print("====== onPenNavUIDismiss =========") self.view().removeFromSuperview() } /** * Called when a report issue is generated. * * @param issue The type of issue reported. */ func onReportIssue(_ issue: PenNavUI.IssueType) { // Handle report issue events if needed print("====== onReportIssueError =========") methodChannel.invokeMethod("onReportIssue", arguments: ["issueType": issue]) } /** * Called when the Penguin UI setup is successful. */ // func onPenNavInitializationSuccess() { // isInitilized = true // if let referenceId = referenceId { // navigator?.navigateToPOI(referenceId: referenceId){ [self] success, errorMessage in // // channel?.invokeMethod(PenguinMethod.navigateToPOI.rawValue, arguments: errorMessage) // // } // } // // channel?.invokeMethod(PenguinMethod.onPenNavSuccess.rawValue, arguments: nil) // } func onPenNavInitializationSuccess() { print("====== onPenNavSuccess =========") onSuccess?() methodChannel.invokeMethod("onPenNavSuccess", arguments: nil) // Obtain the FlutterViewController instance let controller: FlutterViewController = UIApplication.shared.windows.first?.rootViewController as! FlutterViewController print("====== after controller onPenNavSuccess =========") _view = UIView(frame: UIScreen.main.bounds) _view.backgroundColor = .clear controller.view.addSubview(_view) // Set the events delegate to handle SDK events PenNavUIManager.shared.eventsDelegate = self print("====== after eventsDelegate onPenNavSuccess =========") // Present the Penguin UI on top of the Flutter view controller PenNavUIManager.shared.present(root: controller, view: _view) print("====== after present onPenNavSuccess =========") print(model?.clinicID) print("====== after present onPenNavSuccess =========") guard let config = self.model else { print("Error: Config Model is nil") return } guard let clinicID = self.model?.clinicID, let clientID = self.model?.clientID, !clientID.isEmpty else { print("Error: Config Client ID is nil or empty") return } let navigator = PenguinNavigator(config: config) PenNavUIManager.shared.getToken(clientID: config.clientID, clientKey: config.clientKey, showProgress: false) { [weak self] token, error in if let error = error { let errorMessage = "Token error while getting the for Navigate to method" print("Failed to get token: \(errorMessage)") return } guard let token = token else { print("Token is nil") return } print("Token Generated") print(token); self?.handleNavigation(clinicID: clinicID, token: token) { success, errorMessage in if success { print("Navigation successful") } else { print("Navigation failed: \(errorMessage ?? "Unknown error")") } } print("====== after Token onPenNavSuccess =========") } } private func handleNavigation(clinicID: String, token: String, completion: @escaping (Bool, String?) -> Void) { DispatchQueue.main.async { PenNavUIManager.shared.setToken(token: token) PenNavUIManager.shared.navigate(to: clinicID) completion(true,nil) } } /** * Called when there is an initialization error with the Penguin UI. * * @param errorType The type of initialization error. * @param errorDescription A description of the error. */ func onPenNavInitializationError(errorType: PenNavUI.PenNavUIError, errorDescription: String) { // Handle initialization errors if needed print("onPenNavInitializationErrorType: \(errorType.rawValue)") print("onPenNavInitializationError: \(errorDescription)") } }