diff --git a/loans/ios/Classes/ScLoanFlutterPlugin.swift b/loans/ios/Classes/ScLoanFlutterPlugin.swift index 667778c..b388c93 100644 --- a/loans/ios/Classes/ScLoanFlutterPlugin.swift +++ b/loans/ios/Classes/ScLoanFlutterPlugin.swift @@ -9,10 +9,47 @@ import Flutter import UIKit import Loans +@MainActor public class SwiftScLoanFlutterPlugin: NSObject, FlutterPlugin { - - @MainActor - let currentViewController: UIViewController = (UIApplication.shared.delegate?.window??.rootViewController)! + + var currentViewController: UIViewController { + let foregroundScene = UIApplication.shared.connectedScenes + .filter({ $0.activationState == .foregroundActive }) + .compactMap({ $0 as? UIWindowScene }) + .first + + if let scene = foregroundScene { + let keyWindow: UIWindow? + if #available(iOS 15.0, *) { + keyWindow = scene.keyWindow + } else { + keyWindow = scene.windows.first(where: { $0.isKeyWindow }) + } + if let rootVC = keyWindow?.rootViewController { + return rootVC + } + } + + if let windowScene = UIApplication.shared.connectedScenes + .compactMap({ $0 as? UIWindowScene }) + .first { + let window: UIWindow? + if #available(iOS 15.0, *) { + window = windowScene.keyWindow ?? windowScene.windows.first + } else { + window = windowScene.windows.first(where: { $0.isKeyWindow }) ?? windowScene.windows.first + } + if let rootVC = window?.rootViewController { + return rootVC + } + } + + if let rootVC = UIApplication.shared.delegate?.window??.rootViewController { + return rootVC + } + + fatalError("SwiftScLoanFlutterPlugin: No root view controller found. Ensure a UIWindow is set up in SceneDelegate or AppDelegate.") + } public static func register(with registrar: FlutterPluginRegistrar) { let channel = FlutterMethodChannel(name: "scloans", binaryMessenger: registrar.messenger()) diff --git a/scgateway/android/build.gradle b/scgateway/android/build.gradle index 431cf4c..3d3c819 100644 --- a/scgateway/android/build.gradle +++ b/scgateway/android/build.gradle @@ -64,5 +64,5 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation 'com.smallcase.gateway:sdk:6.0.8' + implementation 'com.smallcase.gateway:sdk:6.1.0' } diff --git a/scgateway/android/src/main/kotlin/com/example/scgateway_flutter_plugin/ScgatewayFlutterPluginTxnExt.kt b/scgateway/android/src/main/kotlin/com/example/scgateway_flutter_plugin/ScgatewayFlutterPluginTxnExt.kt index 37ddfa0..69db1a2 100644 --- a/scgateway/android/src/main/kotlin/com/example/scgateway_flutter_plugin/ScgatewayFlutterPluginTxnExt.kt +++ b/scgateway/android/src/main/kotlin/com/example/scgateway_flutter_plugin/ScgatewayFlutterPluginTxnExt.kt @@ -57,6 +57,15 @@ fun ScgatewayFlutterPlugin.txnOnSuccessCallback(transactionResult: TransactionRe result.success(transRes.toString()) + } + SmallcaseGatewaySdk.Result.IMR_SETUP -> { + + val transRes = JSONObject(transactionResult.data!!) + transRes.put("success", true) + transRes.put("transaction", "IMR_SETUP") + + result.success(transRes.toString()) + } else -> { @@ -68,6 +77,7 @@ fun ScgatewayFlutterPlugin.txnOnSuccessCallback(transactionResult: TransactionRe } catch (e: Exception) { e.printStackTrace() + result.error("TXN_ERROR", e.message ?: "Unknown error in transaction callback", null) } } diff --git a/scgateway/ios/Classes/SwiftScgatewayFlutterPlugin.swift b/scgateway/ios/Classes/SwiftScgatewayFlutterPlugin.swift index 0299f23..027d38a 100644 --- a/scgateway/ios/Classes/SwiftScgatewayFlutterPlugin.swift +++ b/scgateway/ios/Classes/SwiftScgatewayFlutterPlugin.swift @@ -8,17 +8,57 @@ enum IntentType: String { case holding = "HOLDINGS_IMPORT" case fetchFunds = "FETCH_FUNDS" case sipSetup = "SIP_SETUP" + case imrSetup = "IMR_SETUP" case authoriseHoldings = "AUTHORISE_HOLDINGS" } +@MainActor public class SwiftScgatewayFlutterPlugin: NSObject, FlutterPlugin, FlutterStreamHandler { - @MainActor - let currentViewController: UIViewController = (UIApplication.shared.delegate?.window??.rootViewController)! - private var eventSink: FlutterEventSink? private var notificationObserver: NSObjectProtocol? + var currentViewController: UIViewController { + let foregroundScene = UIApplication.shared.connectedScenes + .filter({ $0.activationState == .foregroundActive }) + .compactMap({ $0 as? UIWindowScene }) + .first + + if let scene = foregroundScene { + let keyWindow: UIWindow? + if #available(iOS 15.0, *) { + keyWindow = scene.keyWindow + } else { + keyWindow = scene.windows.first(where: { $0.isKeyWindow }) + } + if let rootVC = keyWindow?.rootViewController { + return rootVC + } + } + + // Any connected scene fallback (covers edge cases where no scene is .foregroundActive yet) + if let windowScene = UIApplication.shared.connectedScenes + .compactMap({ $0 as? UIWindowScene }) + .first { + let window: UIWindow? + if #available(iOS 15.0, *) { + window = windowScene.keyWindow ?? windowScene.windows.first + } else { + window = windowScene.windows.first(where: { $0.isKeyWindow }) ?? windowScene.windows.first + } + if let rootVC = window?.rootViewController { + return rootVC + } + } + + // Fallback (AppDelegate-based window) + if let rootVC = UIApplication.shared.delegate?.window??.rootViewController { + return rootVC + } + + fatalError("SwiftScgatewayFlutterPlugin: No root view controller found. Ensure a UIWindow is set up in SceneDelegate or AppDelegate.") + } + public static func register(with registrar: FlutterPluginRegistrar) { let channel = FlutterMethodChannel(name: "scgateway_flutter_plugin", binaryMessenger: registrar.messenger()) let instance = SwiftScgatewayFlutterPlugin() @@ -342,6 +382,40 @@ public class SwiftScgatewayFlutterPlugin: NSObject, FlutterPlugin, FlutterStream /// Catch exception } + // MARK: IMR_SETUP + case .imrSetup(let smallcaseAuthToken, let imrAction, let transactionId, let signup): + + do { + let jsonEncoder = JSONEncoder() + let jsonData = try jsonEncoder.encode(imrAction) + + let data = try? JSONSerialization.jsonObject(with: jsonData, options: []) + + if let imrResponse = data as? [String: Any] { + + print("IMR_SETUP response: \(imrResponse)") + + var resDict: [String: Any] = [:] + + resDict["success"] = true + resDict["data"] = imrResponse + resDict["smallcaseAuthToken"] = smallcaseAuthToken + resDict["transaction"] = "IMR_SETUP" + resDict["transactionId"] = transactionId + resDict["signup"] = signup + + let jsonData = try JSONSerialization.data(withJSONObject: resDict, options: []) + let jsonString = String(data: jsonData, encoding: .utf8) + + result(jsonString) + + return + } + + } catch { + result(FlutterError(code: "IMR_SETUP_ERROR", message: error.localizedDescription, details: nil)) + } + default: return } diff --git a/scgateway/ios/scgateway_flutter_plugin.podspec b/scgateway/ios/scgateway_flutter_plugin.podspec index 4590987..7c3e438 100644 --- a/scgateway/ios/scgateway_flutter_plugin.podspec +++ b/scgateway/ios/scgateway_flutter_plugin.podspec @@ -15,7 +15,7 @@ Scgateway Flutter plugin. s.source = { :path => '.' } s.source_files = 'Classes/**/*' s.dependency 'Flutter' - s.dependency 'SCGateway', '7.1.7' + s.dependency 'SCGateway', '7.2.0' s.xcconfig = {'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES'} s.vendored_frameworks = 'SCGateway.xcframework' s.platform = :ios, '13.0' diff --git a/scgateway/lib/scgateway_flutter_plugin.dart b/scgateway/lib/scgateway_flutter_plugin.dart index 6479d0f..737cf8c 100644 --- a/scgateway/lib/scgateway_flutter_plugin.dart +++ b/scgateway/lib/scgateway_flutter_plugin.dart @@ -13,6 +13,7 @@ class ScgatewayIntent { static const AUTHORISE_HOLDINGS = "AUTHORISE_HOLDINGS"; static const FETCH_FUNDS = "FETCH_FUNDS"; static const SIP_SETUP = "SIP_SETUP"; + static const IMR_SETUP = "IMR_SETUP"; static const CANCEL_AMO = "CANCEL_AMO"; static const MF_HOLDINGS_IMPORT = "MF_HOLDINGS_IMPORT"; } diff --git a/smart_investing/ios/Podfile b/smart_investing/ios/Podfile index a6ab13a..eedcb56 100644 --- a/smart_investing/ios/Podfile +++ b/smart_investing/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '14.0' +platform :ios, '15.0' source 'https://cdn.cocoapods.org' # private podspec for smallcase diff --git a/smart_investing/ios/Podfile.lock b/smart_investing/ios/Podfile.lock index 165f0e2..92bfd34 100644 --- a/smart_investing/ios/Podfile.lock +++ b/smart_investing/ios/Podfile.lock @@ -6,14 +6,14 @@ PODS: - mixpanel_flutter (2.4.4): - Flutter - Mixpanel-swift (= 5.1.0) - - SCGateway (7.1.7) + - SCGateway-dhruv-migrate-to-sceneDelegate-007ae6e (7.1.6-24-debug) - scgateway_flutter_plugin (0.0.1): - Flutter - - SCGateway (= 7.1.7) + - SCGateway-dhruv-migrate-to-sceneDelegate-007ae6e (= 7.1.6-24-debug) - scloans (0.0.1): - Flutter - - SCLoans (= 7.1.2) - - SCLoans (7.1.2) + - SCLoans-dhruv-migrate-to-sceneDelegate-80eca69 (= 7.1.1-39-debug) + - SCLoans-dhruv-migrate-to-sceneDelegate-80eca69 (7.1.1-39-debug) DEPENDENCIES: - Flutter (from `Flutter`) @@ -22,10 +22,11 @@ DEPENDENCIES: - scloans (from `.symlinks/plugins/scloans/ios`) SPEC REPOS: + https://github.com/smallcase/cocoapodspec-internal.git: + - SCGateway-dhruv-migrate-to-sceneDelegate-007ae6e + - SCLoans-dhruv-migrate-to-sceneDelegate-80eca69 trunk: - Mixpanel-swift - - SCGateway - - SCLoans EXTERNAL SOURCES: Flutter: @@ -41,11 +42,11 @@ SPEC CHECKSUMS: Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 Mixpanel-swift: 7b26468fc0e2e521104e51d65c4bbf7cab8162f8 mixpanel_flutter: a0b6b937035899cd01951735ad5f87718b2ffee5 - SCGateway: a0f1bc86e449c7d440d8661e0936095b6f345179 - scgateway_flutter_plugin: 604e1c130e22438e5243d8b841c97f06edff01be - SCLoans: 4accc0a0a483f3943cc513a50800485201fed4dd - scloans: b53430d71d481c4770f13506722d2ab6d26a92ff + SCGateway-dhruv-migrate-to-sceneDelegate-007ae6e: b09149fc113aa409ad828253763c720520a2b642 + scgateway_flutter_plugin: 3ed28fc720e0fdf9ca79c638509a5310788ce48b + scloans: 3c4c1632b4a972373933c81cf91b70265b9a606b + SCLoans-dhruv-migrate-to-sceneDelegate-80eca69: ab2115d77604c531216613247d237a8b08e283a4 -PODFILE CHECKSUM: 32b0659ca3529b1ef2c9e5c229290749c8c79710 +PODFILE CHECKSUM: 06f3d79628f5881e8468842b1f97f7d12c291209 COCOAPODS: 1.16.2 diff --git a/smart_investing/ios/Runner/AppDelegate.swift b/smart_investing/ios/Runner/AppDelegate.swift index 6266644..b7ca7b9 100644 --- a/smart_investing/ios/Runner/AppDelegate.swift +++ b/smart_investing/ios/Runner/AppDelegate.swift @@ -2,12 +2,15 @@ import Flutter import UIKit @main -@objc class AppDelegate: FlutterAppDelegate { +@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { - GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } + + nonisolated func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { + GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) + } } diff --git a/smart_investing/ios/Runner/Info.plist b/smart_investing/ios/Runner/Info.plist index 804112c..83adf60 100644 --- a/smart_investing/ios/Runner/Info.plist +++ b/smart_investing/ios/Runner/Info.plist @@ -83,5 +83,26 @@ UIApplicationSupportsIndirectInputEvents + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneClassName + UIWindowScene + UISceneConfigurationName + flutter + UISceneDelegateClassName + FlutterSceneDelegate + UISceneStoryboardFile + Main + + + + diff --git a/smart_investing/pubspec.lock b/smart_investing/pubspec.lock index 69d2728..f4b370a 100644 --- a/smart_investing/pubspec.lock +++ b/smart_investing/pubspec.lock @@ -109,10 +109,10 @@ packages: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" checked_yaml: dependency: transitive description: @@ -412,26 +412,26 @@ packages: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.19" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" meta: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" mime: dependency: transitive description: @@ -518,14 +518,14 @@ packages: path: "../scgateway" relative: true source: path - version: "7.0.7" + version: "7.0.5" scloans: dependency: "direct main" description: path: "../loans" relative: true source: path - version: "5.1.3" + version: "5.1.1" shelf: dependency: transitive description: @@ -607,10 +607,10 @@ packages: dependency: transitive description: name: test_api - sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" + sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" url: "https://pub.dev" source: hosted - version: "0.7.6" + version: "0.7.10" timing: dependency: transitive description: @@ -676,5 +676,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.8.1 <4.0.0" + dart: ">=3.9.0-0 <4.0.0" flutter: ">=3.18.0-18.0.pre.54"