| @ -0,0 +1,7 @@ | |||
| <html> | |||
| <body> | |||
| <script> | |||
| window.location = "https://docs.pwabuilder.com/#/builder/app-store?id=building-your-app"; | |||
| </script> | |||
| </body> | |||
| </html> | |||
| @ -0,0 +1,92 @@ | |||
| # Xcode | |||
| # | |||
| # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore | |||
| ## User settings | |||
| xcuserdata/ | |||
| ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) | |||
| *.xcscmblueprint | |||
| *.xccheckout | |||
| ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) | |||
| build/ | |||
| DerivedData/ | |||
| *.moved-aside | |||
| *.pbxuser | |||
| !default.pbxuser | |||
| *.mode1v3 | |||
| !default.mode1v3 | |||
| *.mode2v3 | |||
| !default.mode2v3 | |||
| *.perspectivev3 | |||
| !default.perspectivev3 | |||
| ## Obj-C/Swift specific | |||
| *.hmap | |||
| ## App packaging | |||
| *.ipa | |||
| *.dSYM.zip | |||
| *.dSYM | |||
| ## Playgrounds | |||
| timeline.xctimeline | |||
| playground.xcworkspace | |||
| # Swift Package Manager | |||
| # | |||
| # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. | |||
| # Packages/ | |||
| # Package.pins | |||
| # Package.resolved | |||
| # *.xcodeproj | |||
| # | |||
| # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata | |||
| # hence it is not needed unless you have added a package configuration file to your project | |||
| # .swiftpm | |||
| .build/ | |||
| # CocoaPods | |||
| # | |||
| # We recommend against adding the Pods directory to your .gitignore. However | |||
| # you should judge for yourself, the pros and cons are mentioned at: | |||
| # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control | |||
| # | |||
| # Pods/ | |||
| # | |||
| # Add this line if you want to avoid checking in source code from the Xcode workspace | |||
| # *.xcworkspace | |||
| # Carthage | |||
| # | |||
| # Add this line if you want to avoid checking in source code from Carthage dependencies. | |||
| # Carthage/Checkouts | |||
| Carthage/Build/ | |||
| # Accio dependency management | |||
| Dependencies/ | |||
| .accio/ | |||
| # fastlane | |||
| # | |||
| # It is recommended to not store the screenshots in the git repo. | |||
| # Instead, use fastlane to re-generate the screenshots whenever they are needed. | |||
| # For more information about the recommended setup visit: | |||
| # https://docs.fastlane.tools/best-practices/source-control/#source-control | |||
| fastlane/report.xml | |||
| fastlane/Preview.html | |||
| fastlane/screenshots/**/*.png | |||
| fastlane/test_output | |||
| # Code Injection | |||
| # | |||
| # After new code Injection tools there's a generated folder /iOSInjectionProject | |||
| # https://github.com/johnno1962/injectionforxcode | |||
| iOSInjectionProject/ | |||
| /Podfile.lock | |||
| /Pods | |||
| @ -0,0 +1,39 @@ | |||
| import UIKit | |||
| import WebKit | |||
| class CheckoutPaymentViewController: UIViewController, WKNavigationDelegate { | |||
| var checkoutUrl: String? // Razorpay checkout URL | |||
| var wkWebView: WKWebView! | |||
| override func viewDidLoad() { | |||
| super.viewDidLoad() | |||
| // Initialize WebView | |||
| wkWebView = WKWebView(frame: self.view.frame) | |||
| wkWebView.navigationDelegate = self | |||
| self.view.addSubview(wkWebView) | |||
| self.loadWebPage() | |||
| } | |||
| func loadWebPage() { | |||
| guard let urlString = self.checkoutUrl else { return } | |||
| guard let url = URL(string: urlString) else { return } | |||
| self.wkWebView.load(URLRequest(url: url)) | |||
| } | |||
| // Handle Payment Success or Failure (Optional) | |||
| func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { | |||
| if let url = navigationAction.request.url?.absoluteString { | |||
| if url.contains("success") { | |||
| print("Payment Successful") | |||
| self.dismiss(animated: true, completion: nil) // Dismiss ViewController on Success | |||
| } else if url.contains("failure") { | |||
| print("Payment Failed") | |||
| } | |||
| } | |||
| decisionHandler(.allow) | |||
| } | |||
| } | |||
| @ -0,0 +1,38 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||
| <plist version="1.0"> | |||
| <dict> | |||
| <key>CLIENT_ID</key> | |||
| <string>9350938798-9pjd1etaka84smk519q61iclr52iu64s.apps.googleusercontent.com</string> | |||
| <key>REVERSED_CLIENT_ID</key> | |||
| <string>com.googleusercontent.apps.9350938798-9pjd1etaka84smk519q61iclr52iu64s</string> | |||
| <key>ANDROID_CLIENT_ID</key> | |||
| <string>9350938798-1nmut59vc84ap49t076qine91qpsetal.apps.googleusercontent.com</string> | |||
| <key>API_KEY</key> | |||
| <string>AIzaSyAFHcM26WF_WlaVjgN0AO_LfHKeluNU4vM</string> | |||
| <key>GCM_SENDER_ID</key> | |||
| <string>9350938798</string> | |||
| <key>PLIST_VERSION</key> | |||
| <string>1</string> | |||
| <key>BUNDLE_ID</key> | |||
| <string>com.nivesh.app</string> | |||
| <key>PROJECT_ID</key> | |||
| <string>firebase-nivesh</string> | |||
| <key>STORAGE_BUCKET</key> | |||
| <string>firebase-nivesh.appspot.com</string> | |||
| <key>IS_ADS_ENABLED</key> | |||
| <false></false> | |||
| <key>IS_ANALYTICS_ENABLED</key> | |||
| <false></false> | |||
| <key>IS_APPINVITE_ENABLED</key> | |||
| <true></true> | |||
| <key>IS_GCM_ENABLED</key> | |||
| <true></true> | |||
| <key>IS_SIGNIN_ENABLED</key> | |||
| <true></true> | |||
| <key>GOOGLE_APP_ID</key> | |||
| <string>1:9350938798:ios:e85e4205437e211450ed3f</string> | |||
| <key>DATABASE_URL</key> | |||
| <string>https://fir-nivesh.firebaseio.com</string> | |||
| </dict> | |||
| </plist> | |||
| @ -0,0 +1,24 @@ | |||
| This is free and unencumbered software released into the public domain. | |||
| Anyone is free to copy, modify, publish, use, compile, sell, or | |||
| distribute this software, either in source code form or as a compiled | |||
| binary, for any purpose, commercial or non-commercial, and by any | |||
| means. | |||
| In jurisdictions that recognize copyright laws, the author or authors | |||
| of this software dedicate any and all copyright interest in the | |||
| software to the public domain. We make this dedication for the benefit | |||
| of the public at large and to the detriment of our heirs and | |||
| successors. We intend this dedication to be an overt act of | |||
| relinquishment in perpetuity of all present and future rights to this | |||
| software under copyright law. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR | |||
| OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |||
| ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |||
| OTHER DEALINGS IN THE SOFTWARE. | |||
| For more information, please refer to <https://unlicense.org> | |||
| @ -0,0 +1,507 @@ | |||
| // !$*UTF8*$! | |||
| { | |||
| archiveVersion = 1; | |||
| classes = { | |||
| }; | |||
| objectVersion = 54; | |||
| objects = { | |||
| /* Begin PBXBuildFile section */ | |||
| 1E01BF082D50AB030044ED2D /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 1E01BF072D50AB030044ED2D /* GoogleService-Info.plist */; }; | |||
| 1EBE67732D50CF2300F6C6D0 /* FirebaseAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = 1EBE67722D50CF2300F6C6D0 /* FirebaseAnalytics */; }; | |||
| 1EBE67752D50CF2300F6C6D0 /* FirebaseAppCheck in Frameworks */ = {isa = PBXBuildFile; productRef = 1EBE67742D50CF2300F6C6D0 /* FirebaseAppCheck */; }; | |||
| 1EBE67772D50CF2300F6C6D0 /* FirebaseAuth in Frameworks */ = {isa = PBXBuildFile; productRef = 1EBE67762D50CF2300F6C6D0 /* FirebaseAuth */; }; | |||
| 1EBE67792D50CF2300F6C6D0 /* FirebaseCore in Frameworks */ = {isa = PBXBuildFile; productRef = 1EBE67782D50CF2300F6C6D0 /* FirebaseCore */; }; | |||
| 1EBE677B2D50CF2300F6C6D0 /* FirebaseCrashlytics in Frameworks */ = {isa = PBXBuildFile; productRef = 1EBE677A2D50CF2300F6C6D0 /* FirebaseCrashlytics */; }; | |||
| 1EBE677D2D50CF2300F6C6D0 /* FirebaseDynamicLinks in Frameworks */ = {isa = PBXBuildFile; productRef = 1EBE677C2D50CF2300F6C6D0 /* FirebaseDynamicLinks */; }; | |||
| 1EBE677F2D50CF2300F6C6D0 /* FirebaseMessaging in Frameworks */ = {isa = PBXBuildFile; productRef = 1EBE677E2D50CF2300F6C6D0 /* FirebaseMessaging */; }; | |||
| 1EBE67812D50CF2300F6C6D0 /* FirebasePerformance in Frameworks */ = {isa = PBXBuildFile; productRef = 1EBE67802D50CF2300F6C6D0 /* FirebasePerformance */; }; | |||
| 1EBE67852D54952900F6C6D0 /* BranchSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 1EBE67842D54952900F6C6D0 /* BranchSDK */; }; | |||
| 1EBE67882D54958E00F6C6D0 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1EBE67872D54958E00F6C6D0 /* CoreServices.framework */; }; | |||
| 1EBE678A2D5495A900F6C6D0 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1EBE67892D5495A900F6C6D0 /* SystemConfiguration.framework */; }; | |||
| 1EBE678C2D5495B900F6C6D0 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1EBE678B2D5495B900F6C6D0 /* WebKit.framework */; }; | |||
| 1EBE678E2D5495D000F6C6D0 /* CoreSpotlight.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1EBE678D2D5495D000F6C6D0 /* CoreSpotlight.framework */; }; | |||
| 595F23A525CEFBFE0053416C /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 595F239A25CEFBFD0053416C /* Settings.swift */; }; | |||
| 595F23A625CEFBFE0053416C /* Entitlements in Resources */ = {isa = PBXBuildFile; fileRef = 595F239B25CEFBFD0053416C /* Entitlements */; }; | |||
| 595F23A725CEFBFE0053416C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 595F239C25CEFBFD0053416C /* Assets.xcassets */; }; | |||
| 595F23A825CEFBFE0053416C /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 595F239D25CEFBFD0053416C /* SceneDelegate.swift */; }; | |||
| 595F23AA25CEFBFE0053416C /* PushNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 595F239F25CEFBFE0053416C /* PushNotifications.swift */; }; | |||
| 595F23AC25CEFBFE0053416C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 595F23A125CEFBFE0053416C /* ViewController.swift */; }; | |||
| 595F23AD25CEFBFE0053416C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 595F23A225CEFBFE0053416C /* AppDelegate.swift */; }; | |||
| 595F23AE25CEFBFE0053416C /* Printer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 595F23A325CEFBFE0053416C /* Printer.swift */; }; | |||
| 595F23AF25CEFBFE0053416C /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 595F23A425CEFBFE0053416C /* WebView.swift */; }; | |||
| CDC0FE292388222C002C8D56 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CDC0FE252388222B002C8D56 /* Main.storyboard */; }; | |||
| CDC0FE2A2388222C002C8D56 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CDC0FE272388222B002C8D56 /* LaunchScreen.storyboard */; }; | |||
| /* End PBXBuildFile section */ | |||
| /* Begin PBXFileReference section */ | |||
| 1E01BF072D50AB030044ED2D /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; }; | |||
| 1EBE67822D54865300F6C6D0 /* NiveshRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = NiveshRelease.entitlements; path = Nivesh/NiveshRelease.entitlements; sourceTree = "<group>"; }; | |||
| 1EBE67872D54958E00F6C6D0 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; }; | |||
| 1EBE67892D5495A900F6C6D0 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; | |||
| 1EBE678B2D5495B900F6C6D0 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; | |||
| 1EBE678D2D5495D000F6C6D0 /* CoreSpotlight.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreSpotlight.framework; path = System/Library/Frameworks/CoreSpotlight.framework; sourceTree = SDKROOT; }; | |||
| 59333BAA25CFF706003392A4 /* Nivesh.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Nivesh.app; sourceTree = BUILT_PRODUCTS_DIR; }; | |||
| 595F239A25CEFBFD0053416C /* Settings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Settings.swift; path = Nivesh/Settings.swift; sourceTree = "<group>"; }; | |||
| 595F239B25CEFBFD0053416C /* Entitlements */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Entitlements; path = Nivesh/Entitlements; sourceTree = "<group>"; }; | |||
| 595F239C25CEFBFD0053416C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Nivesh/Assets.xcassets; sourceTree = "<group>"; }; | |||
| 595F239D25CEFBFD0053416C /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SceneDelegate.swift; path = Nivesh/SceneDelegate.swift; sourceTree = "<group>"; }; | |||
| 595F239F25CEFBFE0053416C /* PushNotifications.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PushNotifications.swift; path = Nivesh/PushNotifications.swift; sourceTree = "<group>"; }; | |||
| 595F23A025CEFBFE0053416C /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Nivesh/Info.plist; sourceTree = "<group>"; }; | |||
| 595F23A125CEFBFE0053416C /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ViewController.swift; path = Nivesh/ViewController.swift; sourceTree = "<group>"; }; | |||
| 595F23A225CEFBFE0053416C /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = Nivesh/AppDelegate.swift; sourceTree = "<group>"; }; | |||
| 595F23A325CEFBFE0053416C /* Printer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Printer.swift; path = Nivesh/Printer.swift; sourceTree = "<group>"; }; | |||
| 595F23A425CEFBFE0053416C /* WebView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebView.swift; path = Nivesh/WebView.swift; sourceTree = "<group>"; }; | |||
| CDC0FE262388222B002C8D56 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Nivesh/Base.lproj/Main.storyboard; sourceTree = "<group>"; }; | |||
| CDC0FE282388222B002C8D56 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Nivesh/Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; | |||
| /* End PBXFileReference section */ | |||
| /* Begin PBXFrameworksBuildPhase section */ | |||
| CD89F886237E9D9200C436A1 /* Frameworks */ = { | |||
| isa = PBXFrameworksBuildPhase; | |||
| buildActionMask = 2147483647; | |||
| files = ( | |||
| 1EBE67852D54952900F6C6D0 /* BranchSDK in Frameworks */, | |||
| 1EBE67882D54958E00F6C6D0 /* CoreServices.framework in Frameworks */, | |||
| 1EBE678A2D5495A900F6C6D0 /* SystemConfiguration.framework in Frameworks */, | |||
| 1EBE678C2D5495B900F6C6D0 /* WebKit.framework in Frameworks */, | |||
| 1EBE678E2D5495D000F6C6D0 /* CoreSpotlight.framework in Frameworks */, | |||
| 1EBE677F2D50CF2300F6C6D0 /* FirebaseMessaging in Frameworks */, | |||
| 1EBE67732D50CF2300F6C6D0 /* FirebaseAnalytics in Frameworks */, | |||
| 1EBE67812D50CF2300F6C6D0 /* FirebasePerformance in Frameworks */, | |||
| 1EBE67792D50CF2300F6C6D0 /* FirebaseCore in Frameworks */, | |||
| 1EBE67752D50CF2300F6C6D0 /* FirebaseAppCheck in Frameworks */, | |||
| 1EBE677B2D50CF2300F6C6D0 /* FirebaseCrashlytics in Frameworks */, | |||
| 1EBE677D2D50CF2300F6C6D0 /* FirebaseDynamicLinks in Frameworks */, | |||
| 1EBE67772D50CF2300F6C6D0 /* FirebaseAuth in Frameworks */, | |||
| ); | |||
| runOnlyForDeploymentPostprocessing = 0; | |||
| }; | |||
| /* End PBXFrameworksBuildPhase section */ | |||
| /* Begin PBXGroup section */ | |||
| 1EBE67862D54958E00F6C6D0 /* Frameworks */ = { | |||
| isa = PBXGroup; | |||
| children = ( | |||
| 1EBE678D2D5495D000F6C6D0 /* CoreSpotlight.framework */, | |||
| 1EBE678B2D5495B900F6C6D0 /* WebKit.framework */, | |||
| 1EBE67892D5495A900F6C6D0 /* SystemConfiguration.framework */, | |||
| 1EBE67872D54958E00F6C6D0 /* CoreServices.framework */, | |||
| ); | |||
| name = Frameworks; | |||
| sourceTree = "<group>"; | |||
| }; | |||
| 30FCACC6A7BF53CD6D9CF6C0 /* Pods */ = { | |||
| isa = PBXGroup; | |||
| children = ( | |||
| ); | |||
| path = Pods; | |||
| sourceTree = "<group>"; | |||
| }; | |||
| CD89F880237E9D9200C436A1 = { | |||
| isa = PBXGroup; | |||
| children = ( | |||
| 1EBE67822D54865300F6C6D0 /* NiveshRelease.entitlements */, | |||
| 595F23A225CEFBFE0053416C /* AppDelegate.swift */, | |||
| 595F239C25CEFBFD0053416C /* Assets.xcassets */, | |||
| 595F239B25CEFBFD0053416C /* Entitlements */, | |||
| 595F23A025CEFBFE0053416C /* Info.plist */, | |||
| 1E01BF072D50AB030044ED2D /* GoogleService-Info.plist */, | |||
| 595F23A325CEFBFE0053416C /* Printer.swift */, | |||
| 595F239F25CEFBFE0053416C /* PushNotifications.swift */, | |||
| 595F239D25CEFBFD0053416C /* SceneDelegate.swift */, | |||
| 595F239A25CEFBFD0053416C /* Settings.swift */, | |||
| 595F23A125CEFBFE0053416C /* ViewController.swift */, | |||
| CDC0FE272388222B002C8D56 /* LaunchScreen.storyboard */, | |||
| CDC0FE252388222B002C8D56 /* Main.storyboard */, | |||
| 595F23A425CEFBFE0053416C /* WebView.swift */, | |||
| 30FCACC6A7BF53CD6D9CF6C0 /* Pods */, | |||
| 59333BAA25CFF706003392A4 /* Nivesh.app */, | |||
| 1EBE67862D54958E00F6C6D0 /* Frameworks */, | |||
| ); | |||
| sourceTree = "<group>"; | |||
| }; | |||
| /* End PBXGroup section */ | |||
| /* Begin PBXNativeTarget section */ | |||
| CD89F888237E9D9200C436A1 /* Nivesh */ = { | |||
| isa = PBXNativeTarget; | |||
| buildConfigurationList = CD89F89D237E9D9300C436A1 /* Build configuration list for PBXNativeTarget "Nivesh" */; | |||
| buildPhases = ( | |||
| CD89F885237E9D9200C436A1 /* Sources */, | |||
| CD89F886237E9D9200C436A1 /* Frameworks */, | |||
| CD89F887237E9D9200C436A1 /* Resources */, | |||
| ); | |||
| buildRules = ( | |||
| ); | |||
| dependencies = ( | |||
| ); | |||
| name = Nivesh; | |||
| productName = Nivesh; | |||
| productReference = 59333BAA25CFF706003392A4 /* Nivesh.app */; | |||
| productType = "com.apple.product-type.application"; | |||
| }; | |||
| /* End PBXNativeTarget section */ | |||
| /* Begin PBXProject section */ | |||
| CD89F881237E9D9200C436A1 /* Project object */ = { | |||
| isa = PBXProject; | |||
| attributes = { | |||
| BuildIndependentTargetsInParallel = YES; | |||
| LastSwiftUpdateCheck = 1120; | |||
| LastUpgradeCheck = 1620; | |||
| ORGANIZATIONNAME = ""; | |||
| TargetAttributes = { | |||
| CD89F888237E9D9200C436A1 = { | |||
| CreatedOnToolsVersion = 11.2.1; | |||
| LastSwiftMigration = 1120; | |||
| }; | |||
| }; | |||
| }; | |||
| buildConfigurationList = CD89F884237E9D9200C436A1 /* Build configuration list for PBXProject "Nivesh" */; | |||
| compatibilityVersion = "Xcode 11.0"; | |||
| developmentRegion = en; | |||
| hasScannedForEncodings = 0; | |||
| knownRegions = ( | |||
| en, | |||
| Base, | |||
| ); | |||
| mainGroup = CD89F880237E9D9200C436A1; | |||
| packageReferences = ( | |||
| 1EBE67712D50CF2300F6C6D0 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, | |||
| 1EBE67832D54952900F6C6D0 /* XCRemoteSwiftPackageReference "ios-branch-sdk-spm" */, | |||
| ); | |||
| productRefGroup = CD89F880237E9D9200C436A1; | |||
| projectDirPath = ""; | |||
| projectRoot = ""; | |||
| targets = ( | |||
| CD89F888237E9D9200C436A1 /* Nivesh */, | |||
| ); | |||
| }; | |||
| /* End PBXProject section */ | |||
| /* Begin PBXResourcesBuildPhase section */ | |||
| CD89F887237E9D9200C436A1 /* Resources */ = { | |||
| isa = PBXResourcesBuildPhase; | |||
| buildActionMask = 2147483647; | |||
| files = ( | |||
| 595F23A625CEFBFE0053416C /* Entitlements in Resources */, | |||
| CDC0FE292388222C002C8D56 /* Main.storyboard in Resources */, | |||
| 1E01BF082D50AB030044ED2D /* GoogleService-Info.plist in Resources */, | |||
| CDC0FE2A2388222C002C8D56 /* LaunchScreen.storyboard in Resources */, | |||
| 595F23A725CEFBFE0053416C /* Assets.xcassets in Resources */, | |||
| ); | |||
| runOnlyForDeploymentPostprocessing = 0; | |||
| }; | |||
| /* End PBXResourcesBuildPhase section */ | |||
| /* Begin PBXSourcesBuildPhase section */ | |||
| CD89F885237E9D9200C436A1 /* Sources */ = { | |||
| isa = PBXSourcesBuildPhase; | |||
| buildActionMask = 2147483647; | |||
| files = ( | |||
| 595F23AD25CEFBFE0053416C /* AppDelegate.swift in Sources */, | |||
| 595F23A825CEFBFE0053416C /* SceneDelegate.swift in Sources */, | |||
| 595F23A525CEFBFE0053416C /* Settings.swift in Sources */, | |||
| 595F23AE25CEFBFE0053416C /* Printer.swift in Sources */, | |||
| 595F23AC25CEFBFE0053416C /* ViewController.swift in Sources */, | |||
| 595F23AA25CEFBFE0053416C /* PushNotifications.swift in Sources */, | |||
| 595F23AF25CEFBFE0053416C /* WebView.swift in Sources */, | |||
| ); | |||
| runOnlyForDeploymentPostprocessing = 0; | |||
| }; | |||
| /* End PBXSourcesBuildPhase section */ | |||
| /* Begin PBXVariantGroup section */ | |||
| CDC0FE252388222B002C8D56 /* Main.storyboard */ = { | |||
| isa = PBXVariantGroup; | |||
| children = ( | |||
| CDC0FE262388222B002C8D56 /* Base */, | |||
| ); | |||
| name = Main.storyboard; | |||
| sourceTree = "<group>"; | |||
| }; | |||
| CDC0FE272388222B002C8D56 /* LaunchScreen.storyboard */ = { | |||
| isa = PBXVariantGroup; | |||
| children = ( | |||
| CDC0FE282388222B002C8D56 /* Base */, | |||
| ); | |||
| name = LaunchScreen.storyboard; | |||
| sourceTree = "<group>"; | |||
| }; | |||
| /* End PBXVariantGroup section */ | |||
| /* Begin XCBuildConfiguration section */ | |||
| CD89F89B237E9D9300C436A1 /* Debug */ = { | |||
| isa = XCBuildConfiguration; | |||
| buildSettings = { | |||
| ALWAYS_SEARCH_USER_PATHS = NO; | |||
| CLANG_ANALYZER_NONNULL = YES; | |||
| CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; | |||
| CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; | |||
| CLANG_CXX_LIBRARY = "libc++"; | |||
| CLANG_ENABLE_MODULES = YES; | |||
| CLANG_ENABLE_OBJC_ARC = YES; | |||
| CLANG_ENABLE_OBJC_WEAK = YES; | |||
| CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; | |||
| CLANG_WARN_BOOL_CONVERSION = YES; | |||
| CLANG_WARN_COMMA = YES; | |||
| CLANG_WARN_CONSTANT_CONVERSION = YES; | |||
| CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; | |||
| CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; | |||
| CLANG_WARN_DOCUMENTATION_COMMENTS = YES; | |||
| CLANG_WARN_EMPTY_BODY = YES; | |||
| CLANG_WARN_ENUM_CONVERSION = YES; | |||
| CLANG_WARN_INFINITE_RECURSION = YES; | |||
| CLANG_WARN_INT_CONVERSION = YES; | |||
| CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; | |||
| CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; | |||
| CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; | |||
| CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; | |||
| CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; | |||
| CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; | |||
| CLANG_WARN_STRICT_PROTOTYPES = YES; | |||
| CLANG_WARN_SUSPICIOUS_MOVE = YES; | |||
| CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; | |||
| CLANG_WARN_UNREACHABLE_CODE = YES; | |||
| CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | |||
| COPY_PHASE_STRIP = NO; | |||
| DEBUG_INFORMATION_FORMAT = dwarf; | |||
| ENABLE_STRICT_OBJC_MSGSEND = YES; | |||
| ENABLE_TESTABILITY = YES; | |||
| ENABLE_USER_SCRIPT_SANDBOXING = YES; | |||
| GCC_C_LANGUAGE_STANDARD = gnu11; | |||
| GCC_DYNAMIC_NO_PIC = NO; | |||
| GCC_NO_COMMON_BLOCKS = YES; | |||
| GCC_OPTIMIZATION_LEVEL = 0; | |||
| GCC_PREPROCESSOR_DEFINITIONS = ( | |||
| "DEBUG=1", | |||
| "$(inherited)", | |||
| ); | |||
| GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | |||
| GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; | |||
| GCC_WARN_UNDECLARED_SELECTOR = YES; | |||
| GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | |||
| GCC_WARN_UNUSED_FUNCTION = YES; | |||
| GCC_WARN_UNUSED_VARIABLE = YES; | |||
| IPHONEOS_DEPLOYMENT_TARGET = 15.0; | |||
| MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; | |||
| MTL_FAST_MATH = YES; | |||
| ONLY_ACTIVE_ARCH = YES; | |||
| SDKROOT = iphoneos; | |||
| SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; | |||
| SWIFT_OPTIMIZATION_LEVEL = "-Onone"; | |||
| TARGETED_DEVICE_FAMILY = "1,2,6"; | |||
| VALID_ARCHS = "$(ARCHS_STANDARD)"; | |||
| }; | |||
| name = Debug; | |||
| }; | |||
| CD89F89C237E9D9300C436A1 /* Release */ = { | |||
| isa = XCBuildConfiguration; | |||
| buildSettings = { | |||
| ALWAYS_SEARCH_USER_PATHS = NO; | |||
| CLANG_ANALYZER_NONNULL = YES; | |||
| CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; | |||
| CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; | |||
| CLANG_CXX_LIBRARY = "libc++"; | |||
| CLANG_ENABLE_MODULES = YES; | |||
| CLANG_ENABLE_OBJC_ARC = YES; | |||
| CLANG_ENABLE_OBJC_WEAK = YES; | |||
| CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; | |||
| CLANG_WARN_BOOL_CONVERSION = YES; | |||
| CLANG_WARN_COMMA = YES; | |||
| CLANG_WARN_CONSTANT_CONVERSION = YES; | |||
| CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; | |||
| CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; | |||
| CLANG_WARN_DOCUMENTATION_COMMENTS = YES; | |||
| CLANG_WARN_EMPTY_BODY = YES; | |||
| CLANG_WARN_ENUM_CONVERSION = YES; | |||
| CLANG_WARN_INFINITE_RECURSION = YES; | |||
| CLANG_WARN_INT_CONVERSION = YES; | |||
| CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; | |||
| CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; | |||
| CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; | |||
| CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; | |||
| CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; | |||
| CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; | |||
| CLANG_WARN_STRICT_PROTOTYPES = YES; | |||
| CLANG_WARN_SUSPICIOUS_MOVE = YES; | |||
| CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; | |||
| CLANG_WARN_UNREACHABLE_CODE = YES; | |||
| CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | |||
| COPY_PHASE_STRIP = NO; | |||
| DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; | |||
| ENABLE_NS_ASSERTIONS = NO; | |||
| ENABLE_STRICT_OBJC_MSGSEND = YES; | |||
| ENABLE_USER_SCRIPT_SANDBOXING = YES; | |||
| GCC_C_LANGUAGE_STANDARD = gnu11; | |||
| GCC_NO_COMMON_BLOCKS = YES; | |||
| GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | |||
| GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; | |||
| GCC_WARN_UNDECLARED_SELECTOR = YES; | |||
| GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | |||
| GCC_WARN_UNUSED_FUNCTION = YES; | |||
| GCC_WARN_UNUSED_VARIABLE = YES; | |||
| IPHONEOS_DEPLOYMENT_TARGET = 15.0; | |||
| MTL_ENABLE_DEBUG_INFO = NO; | |||
| MTL_FAST_MATH = YES; | |||
| SDKROOT = iphoneos; | |||
| SWIFT_COMPILATION_MODE = wholemodule; | |||
| SWIFT_OPTIMIZATION_LEVEL = "-O"; | |||
| TARGETED_DEVICE_FAMILY = "1,2,6"; | |||
| VALIDATE_PRODUCT = YES; | |||
| VALID_ARCHS = "$(ARCHS_STANDARD)"; | |||
| }; | |||
| name = Release; | |||
| }; | |||
| CD89F89E237E9D9300C436A1 /* Debug */ = { | |||
| isa = XCBuildConfiguration; | |||
| buildSettings = { | |||
| ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | |||
| CLANG_ENABLE_MODULES = NO; | |||
| CODE_SIGN_ENTITLEMENTS = Nivesh/Entitlements/Entitlements.plist; | |||
| CODE_SIGN_IDENTITY = "Apple Development"; | |||
| CODE_SIGN_STYLE = Automatic; | |||
| CURRENT_PROJECT_VERSION = 2; | |||
| DEVELOPMENT_TEAM = 892H6H36S9; | |||
| INFOPLIST_FILE = Nivesh/Info.plist; | |||
| IPHONEOS_DEPLOYMENT_TARGET = 15.0; | |||
| LD_RUNPATH_SEARCH_PATHS = ( | |||
| "$(inherited)", | |||
| "@executable_path/Frameworks", | |||
| ); | |||
| MARKETING_VERSION = 1.1; | |||
| PRODUCT_BUNDLE_IDENTIFIER = com.nivesh.app; | |||
| PRODUCT_NAME = Nivesh; | |||
| PROVISIONING_PROFILE_SPECIFIER = ""; | |||
| SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; | |||
| SUPPORTS_MACCATALYST = NO; | |||
| SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; | |||
| SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; | |||
| SWIFT_OPTIMIZATION_LEVEL = "-Onone"; | |||
| SWIFT_VERSION = 5.0; | |||
| TARGETED_DEVICE_FAMILY = "1,2,6"; | |||
| }; | |||
| name = Debug; | |||
| }; | |||
| CD89F89F237E9D9300C436A1 /* Release */ = { | |||
| isa = XCBuildConfiguration; | |||
| buildSettings = { | |||
| ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | |||
| CLANG_ENABLE_MODULES = NO; | |||
| CODE_SIGN_ENTITLEMENTS = Nivesh/NiveshRelease.entitlements; | |||
| CODE_SIGN_IDENTITY = "Apple Development"; | |||
| CODE_SIGN_STYLE = Automatic; | |||
| CURRENT_PROJECT_VERSION = 2; | |||
| DEVELOPMENT_TEAM = 892H6H36S9; | |||
| INFOPLIST_FILE = Nivesh/Info.plist; | |||
| IPHONEOS_DEPLOYMENT_TARGET = 15.0; | |||
| LD_RUNPATH_SEARCH_PATHS = ( | |||
| "$(inherited)", | |||
| "@executable_path/Frameworks", | |||
| ); | |||
| MARKETING_VERSION = 1.1; | |||
| PRODUCT_BUNDLE_IDENTIFIER = com.nivesh.app; | |||
| PRODUCT_NAME = Nivesh; | |||
| SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; | |||
| SUPPORTS_MACCATALYST = NO; | |||
| SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; | |||
| SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; | |||
| SWIFT_OPTIMIZATION_LEVEL = "-Osize"; | |||
| SWIFT_VERSION = 5.0; | |||
| TARGETED_DEVICE_FAMILY = "1,2,6"; | |||
| }; | |||
| name = Release; | |||
| }; | |||
| /* End XCBuildConfiguration section */ | |||
| /* Begin XCConfigurationList section */ | |||
| CD89F884237E9D9200C436A1 /* Build configuration list for PBXProject "Nivesh" */ = { | |||
| isa = XCConfigurationList; | |||
| buildConfigurations = ( | |||
| CD89F89B237E9D9300C436A1 /* Debug */, | |||
| CD89F89C237E9D9300C436A1 /* Release */, | |||
| ); | |||
| defaultConfigurationIsVisible = 0; | |||
| defaultConfigurationName = Release; | |||
| }; | |||
| CD89F89D237E9D9300C436A1 /* Build configuration list for PBXNativeTarget "Nivesh" */ = { | |||
| isa = XCConfigurationList; | |||
| buildConfigurations = ( | |||
| CD89F89E237E9D9300C436A1 /* Debug */, | |||
| CD89F89F237E9D9300C436A1 /* Release */, | |||
| ); | |||
| defaultConfigurationIsVisible = 0; | |||
| defaultConfigurationName = Release; | |||
| }; | |||
| /* End XCConfigurationList section */ | |||
| /* Begin XCRemoteSwiftPackageReference section */ | |||
| 1EBE67712D50CF2300F6C6D0 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = { | |||
| isa = XCRemoteSwiftPackageReference; | |||
| repositoryURL = "https://github.com/firebase/firebase-ios-sdk"; | |||
| requirement = { | |||
| kind = upToNextMajorVersion; | |||
| minimumVersion = 11.7.0; | |||
| }; | |||
| }; | |||
| 1EBE67832D54952900F6C6D0 /* XCRemoteSwiftPackageReference "ios-branch-sdk-spm" */ = { | |||
| isa = XCRemoteSwiftPackageReference; | |||
| repositoryURL = "https://github.com/BranchMetrics/ios-branch-sdk-spm"; | |||
| requirement = { | |||
| kind = upToNextMajorVersion; | |||
| minimumVersion = 3.8.0; | |||
| }; | |||
| }; | |||
| /* End XCRemoteSwiftPackageReference section */ | |||
| /* Begin XCSwiftPackageProductDependency section */ | |||
| 1EBE67722D50CF2300F6C6D0 /* FirebaseAnalytics */ = { | |||
| isa = XCSwiftPackageProductDependency; | |||
| package = 1EBE67712D50CF2300F6C6D0 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; | |||
| productName = FirebaseAnalytics; | |||
| }; | |||
| 1EBE67742D50CF2300F6C6D0 /* FirebaseAppCheck */ = { | |||
| isa = XCSwiftPackageProductDependency; | |||
| package = 1EBE67712D50CF2300F6C6D0 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; | |||
| productName = FirebaseAppCheck; | |||
| }; | |||
| 1EBE67762D50CF2300F6C6D0 /* FirebaseAuth */ = { | |||
| isa = XCSwiftPackageProductDependency; | |||
| package = 1EBE67712D50CF2300F6C6D0 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; | |||
| productName = FirebaseAuth; | |||
| }; | |||
| 1EBE67782D50CF2300F6C6D0 /* FirebaseCore */ = { | |||
| isa = XCSwiftPackageProductDependency; | |||
| package = 1EBE67712D50CF2300F6C6D0 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; | |||
| productName = FirebaseCore; | |||
| }; | |||
| 1EBE677A2D50CF2300F6C6D0 /* FirebaseCrashlytics */ = { | |||
| isa = XCSwiftPackageProductDependency; | |||
| package = 1EBE67712D50CF2300F6C6D0 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; | |||
| productName = FirebaseCrashlytics; | |||
| }; | |||
| 1EBE677C2D50CF2300F6C6D0 /* FirebaseDynamicLinks */ = { | |||
| isa = XCSwiftPackageProductDependency; | |||
| package = 1EBE67712D50CF2300F6C6D0 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; | |||
| productName = FirebaseDynamicLinks; | |||
| }; | |||
| 1EBE677E2D50CF2300F6C6D0 /* FirebaseMessaging */ = { | |||
| isa = XCSwiftPackageProductDependency; | |||
| package = 1EBE67712D50CF2300F6C6D0 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; | |||
| productName = FirebaseMessaging; | |||
| }; | |||
| 1EBE67802D50CF2300F6C6D0 /* FirebasePerformance */ = { | |||
| isa = XCSwiftPackageProductDependency; | |||
| package = 1EBE67712D50CF2300F6C6D0 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; | |||
| productName = FirebasePerformance; | |||
| }; | |||
| 1EBE67842D54952900F6C6D0 /* BranchSDK */ = { | |||
| isa = XCSwiftPackageProductDependency; | |||
| package = 1EBE67832D54952900F6C6D0 /* XCRemoteSwiftPackageReference "ios-branch-sdk-spm" */; | |||
| productName = BranchSDK; | |||
| }; | |||
| /* End XCSwiftPackageProductDependency section */ | |||
| }; | |||
| rootObject = CD89F881237E9D9200C436A1 /* Project object */; | |||
| } | |||
| @ -0,0 +1,7 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <Workspace | |||
| version = "1.0"> | |||
| <FileRef | |||
| location = "self:Nivesh.xcodeproj"> | |||
| </FileRef> | |||
| </Workspace> | |||
| @ -0,0 +1,8 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||
| <plist version="1.0"> | |||
| <dict> | |||
| <key>IDEDidComputeMac32BitWarning</key> | |||
| <true/> | |||
| </dict> | |||
| </plist> | |||
| @ -0,0 +1,8 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||
| <plist version="1.0"> | |||
| <dict> | |||
| <key>PreviewsEnabled</key> | |||
| <false/> | |||
| </dict> | |||
| </plist> | |||
| @ -0,0 +1,85 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <Scheme | |||
| LastUpgradeVersion = "1620" | |||
| version = "1.3"> | |||
| <BuildAction | |||
| parallelizeBuildables = "YES" | |||
| buildImplicitDependencies = "YES"> | |||
| <BuildActionEntries> | |||
| <BuildActionEntry | |||
| buildForTesting = "YES" | |||
| buildForRunning = "YES" | |||
| buildForProfiling = "YES" | |||
| buildForArchiving = "YES" | |||
| buildForAnalyzing = "YES"> | |||
| <BuildableReference | |||
| BuildableIdentifier = "primary" | |||
| BlueprintIdentifier = "CD89F888237E9D9200C436A1" | |||
| BuildableName = "Nivesh.app" | |||
| BlueprintName = "Nivesh" | |||
| ReferencedContainer = "container:Nivesh.xcodeproj"> | |||
| </BuildableReference> | |||
| </BuildActionEntry> | |||
| </BuildActionEntries> | |||
| </BuildAction> | |||
| <TestAction | |||
| buildConfiguration = "Debug" | |||
| selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" | |||
| selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" | |||
| shouldUseLaunchSchemeArgsEnv = "YES"> | |||
| <Testables> | |||
| </Testables> | |||
| </TestAction> | |||
| <LaunchAction | |||
| buildConfiguration = "Debug" | |||
| selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" | |||
| selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" | |||
| launchStyle = "0" | |||
| useCustomWorkingDirectory = "NO" | |||
| ignoresPersistentStateOnLaunch = "NO" | |||
| debugDocumentVersioning = "YES" | |||
| debugServiceExtension = "internal" | |||
| allowLocationSimulation = "YES"> | |||
| <BuildableProductRunnable | |||
| runnableDebuggingMode = "0"> | |||
| <BuildableReference | |||
| BuildableIdentifier = "primary" | |||
| BlueprintIdentifier = "CD89F888237E9D9200C436A1" | |||
| BuildableName = "Nivesh.app" | |||
| BlueprintName = "Nivesh" | |||
| ReferencedContainer = "container:Nivesh.xcodeproj"> | |||
| </BuildableReference> | |||
| </BuildableProductRunnable> | |||
| <EnvironmentVariables> | |||
| <EnvironmentVariable | |||
| key = "OS_ACTIVITY_MODE" | |||
| value = "disable" | |||
| isEnabled = "YES"> | |||
| </EnvironmentVariable> | |||
| </EnvironmentVariables> | |||
| </LaunchAction> | |||
| <ProfileAction | |||
| buildConfiguration = "Release" | |||
| shouldUseLaunchSchemeArgsEnv = "YES" | |||
| savedToolIdentifier = "" | |||
| useCustomWorkingDirectory = "NO" | |||
| debugDocumentVersioning = "YES"> | |||
| <BuildableProductRunnable | |||
| runnableDebuggingMode = "0"> | |||
| <BuildableReference | |||
| BuildableIdentifier = "primary" | |||
| BlueprintIdentifier = "CD89F888237E9D9200C436A1" | |||
| BuildableName = "Nivesh.app" | |||
| BlueprintName = "Nivesh" | |||
| ReferencedContainer = "container:Nivesh.xcodeproj"> | |||
| </BuildableReference> | |||
| </BuildableProductRunnable> | |||
| </ProfileAction> | |||
| <AnalyzeAction | |||
| buildConfiguration = "Debug"> | |||
| </AnalyzeAction> | |||
| <ArchiveAction | |||
| buildConfiguration = "Release" | |||
| revealArchiveInOrganizer = "YES"> | |||
| </ArchiveAction> | |||
| </Scheme> | |||
| @ -0,0 +1,10 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <Workspace | |||
| version = "1.0"> | |||
| <FileRef | |||
| location = "group:Nivesh.xcodeproj"> | |||
| </FileRef> | |||
| <FileRef | |||
| location = "group:Pods/Pods.xcodeproj"> | |||
| </FileRef> | |||
| </Workspace> | |||
| @ -0,0 +1,8 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||
| <plist version="1.0"> | |||
| <dict> | |||
| <key>IDEDidComputeMac32BitWarning</key> | |||
| <true/> | |||
| </dict> | |||
| </plist> | |||
| @ -0,0 +1,132 @@ | |||
| { | |||
| "originHash" : "d3fa15d926fa0f697cb981b51acbaff616acb7eb437695719dedfca1f38b248c", | |||
| "pins" : [ | |||
| { | |||
| "identity" : "abseil-cpp-binary", | |||
| "kind" : "remoteSourceControl", | |||
| "location" : "https://github.com/google/abseil-cpp-binary.git", | |||
| "state" : { | |||
| "revision" : "194a6706acbd25e4ef639bcaddea16e8758a3e27", | |||
| "version" : "1.2024011602.0" | |||
| } | |||
| }, | |||
| { | |||
| "identity" : "app-check", | |||
| "kind" : "remoteSourceControl", | |||
| "location" : "https://github.com/google/app-check.git", | |||
| "state" : { | |||
| "revision" : "61b85103a1aeed8218f17c794687781505fbbef5", | |||
| "version" : "11.2.0" | |||
| } | |||
| }, | |||
| { | |||
| "identity" : "firebase-ios-sdk", | |||
| "kind" : "remoteSourceControl", | |||
| "location" : "https://github.com/firebase/firebase-ios-sdk", | |||
| "state" : { | |||
| "revision" : "0d885d28250fb1196b614bc9455079b75c531f72", | |||
| "version" : "11.7.0" | |||
| } | |||
| }, | |||
| { | |||
| "identity" : "googleappmeasurement", | |||
| "kind" : "remoteSourceControl", | |||
| "location" : "https://github.com/google/GoogleAppMeasurement.git", | |||
| "state" : { | |||
| "revision" : "be0881ff728eca210ccb628092af400c086abda3", | |||
| "version" : "11.7.0" | |||
| } | |||
| }, | |||
| { | |||
| "identity" : "googledatatransport", | |||
| "kind" : "remoteSourceControl", | |||
| "location" : "https://github.com/google/GoogleDataTransport.git", | |||
| "state" : { | |||
| "revision" : "617af071af9aa1d6a091d59a202910ac482128f9", | |||
| "version" : "10.1.0" | |||
| } | |||
| }, | |||
| { | |||
| "identity" : "googleutilities", | |||
| "kind" : "remoteSourceControl", | |||
| "location" : "https://github.com/google/GoogleUtilities.git", | |||
| "state" : { | |||
| "revision" : "53156c7ec267db846e6b64c9f4c4e31ba4cf75eb", | |||
| "version" : "8.0.2" | |||
| } | |||
| }, | |||
| { | |||
| "identity" : "grpc-binary", | |||
| "kind" : "remoteSourceControl", | |||
| "location" : "https://github.com/google/grpc-binary.git", | |||
| "state" : { | |||
| "revision" : "f56d8fc3162de9a498377c7b6cea43431f4f5083", | |||
| "version" : "1.65.1" | |||
| } | |||
| }, | |||
| { | |||
| "identity" : "gtm-session-fetcher", | |||
| "kind" : "remoteSourceControl", | |||
| "location" : "https://github.com/google/gtm-session-fetcher.git", | |||
| "state" : { | |||
| "revision" : "3cdb78efb79b4a5383c3911488d8025bfc545b5e", | |||
| "version" : "4.3.0" | |||
| } | |||
| }, | |||
| { | |||
| "identity" : "interop-ios-for-google-sdks", | |||
| "kind" : "remoteSourceControl", | |||
| "location" : "https://github.com/google/interop-ios-for-google-sdks.git", | |||
| "state" : { | |||
| "revision" : "2d12673670417654f08f5f90fdd62926dc3a2648", | |||
| "version" : "100.0.0" | |||
| } | |||
| }, | |||
| { | |||
| "identity" : "ios-branch-sdk-spm", | |||
| "kind" : "remoteSourceControl", | |||
| "location" : "https://github.com/BranchMetrics/ios-branch-sdk-spm", | |||
| "state" : { | |||
| "revision" : "37d0fb8ff04098807957b1d387812ed8f96fbdc7", | |||
| "version" : "3.8.0" | |||
| } | |||
| }, | |||
| { | |||
| "identity" : "leveldb", | |||
| "kind" : "remoteSourceControl", | |||
| "location" : "https://github.com/firebase/leveldb.git", | |||
| "state" : { | |||
| "revision" : "a0bc79961d7be727d258d33d5a6b2f1023270ba1", | |||
| "version" : "1.22.5" | |||
| } | |||
| }, | |||
| { | |||
| "identity" : "nanopb", | |||
| "kind" : "remoteSourceControl", | |||
| "location" : "https://github.com/firebase/nanopb.git", | |||
| "state" : { | |||
| "revision" : "b7e1104502eca3a213b46303391ca4d3bc8ddec1", | |||
| "version" : "2.30910.0" | |||
| } | |||
| }, | |||
| { | |||
| "identity" : "promises", | |||
| "kind" : "remoteSourceControl", | |||
| "location" : "https://github.com/google/promises.git", | |||
| "state" : { | |||
| "revision" : "540318ecedd63d883069ae7f1ed811a2df00b6ac", | |||
| "version" : "2.4.0" | |||
| } | |||
| }, | |||
| { | |||
| "identity" : "swift-protobuf", | |||
| "kind" : "remoteSourceControl", | |||
| "location" : "https://github.com/apple/swift-protobuf.git", | |||
| "state" : { | |||
| "revision" : "ebc7251dd5b37f627c93698e4374084d98409633", | |||
| "version" : "1.28.2" | |||
| } | |||
| } | |||
| ], | |||
| "version" : 3 | |||
| } | |||
| @ -0,0 +1,151 @@ | |||
| import UIKit | |||
| import FirebaseCore | |||
| import FirebaseMessaging | |||
| import UserNotifications | |||
| import BranchSDK | |||
| @UIApplicationMain | |||
| class AppDelegate: UIResponder, UIApplicationDelegate { | |||
| var window : UIWindow? | |||
| func application(_ application: UIApplication, | |||
| didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { | |||
| // TODO: if we're using Firebase, uncomment next string | |||
| FirebaseApp.configure() | |||
| // [START set_messaging_delegate] | |||
| Messaging.messaging().delegate = self | |||
| // [END set_messaging_delegate] | |||
| // Register for remote notifications. This shows a permission dialog on first run, to | |||
| // show the dialog at a more appropriate time move this registration accordingly. | |||
| // [START register_for_notifications] | |||
| UNUserNotificationCenter.current().delegate = self | |||
| let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] | |||
| UNUserNotificationCenter.current().requestAuthorization( | |||
| options: authOptions, | |||
| completionHandler: {_, _ in }) | |||
| // TODO: if we're using Firebase, uncomment next string | |||
| application.registerForRemoteNotifications() | |||
| // [END register_for_notifications] | |||
| // This version of `initSession` includes the source UIScene in the callback | |||
| BranchScene.shared().initSession(launchOptions: launchOptions, registerDeepLinkHandler: { (params, error, scene) in | |||
| }) | |||
| return true | |||
| } | |||
| // [START receive_message] | |||
| func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) { | |||
| // If you are receiving a notification message while your app is in the background, | |||
| // this callback will not be fired till the user taps on the notification launching the application. | |||
| // With swizzling disabled you must let Messaging know about the message, for Analytics | |||
| Messaging.messaging().appDidReceiveMessage(userInfo) | |||
| // Print message ID. | |||
| if let messageID = userInfo[gcmMessageIDKey] { | |||
| print("Message ID 1: \(messageID)") | |||
| } | |||
| // Print full message. | |||
| print("push userInfo 1:", userInfo) | |||
| sendPushToWebView(userInfo: userInfo) | |||
| } | |||
| func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], | |||
| fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { | |||
| // If you are receiving a notification message while your app is in the background, | |||
| // this callback will not be fired till the user taps on the notification launching the application. | |||
| // With swizzling disabled you must let Messaging know about the message, for Analytics | |||
| Messaging.messaging().appDidReceiveMessage(userInfo) | |||
| // Print message ID. | |||
| if let messageID = userInfo[gcmMessageIDKey] { | |||
| print("Message ID 2: \(messageID)") | |||
| } | |||
| // Print full message. ** | |||
| print("push userInfo 2:", userInfo) | |||
| sendPushToWebView(userInfo: userInfo) | |||
| completionHandler(UIBackgroundFetchResult.newData) | |||
| } | |||
| // [END receive_message] | |||
| func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { | |||
| print("Unable to register for remote notifications: \(error.localizedDescription)") | |||
| } | |||
| // This function is added here only for debugging purposes, and can be removed if swizzling is enabled. | |||
| // If swizzling is disabled then this function must be implemented so that the APNs token can be paired to | |||
| // the FCM registration token. | |||
| func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { | |||
| print("APNs token retrieved: \(deviceToken)") | |||
| // With swizzling disabled you must set the APNs token here. | |||
| Messaging.messaging().apnsToken = deviceToken | |||
| } | |||
| } | |||
| // [START ios_10_message_handling] | |||
| extension AppDelegate : UNUserNotificationCenterDelegate { | |||
| func userNotificationCenter(_ center: UNUserNotificationCenter, | |||
| willPresent notification: UNNotification, | |||
| withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { | |||
| let userInfo = notification.request.content.userInfo | |||
| // With swizzling disabled you must let Messaging know about the message, for Analytics | |||
| Messaging.messaging().appDidReceiveMessage(userInfo) | |||
| // Print message ID. | |||
| if let messageID = userInfo[gcmMessageIDKey] { | |||
| print("Message ID: 3 \(messageID)") | |||
| } | |||
| // Print full message. | |||
| print("push userInfo 3:", userInfo) | |||
| sendPushToWebView(userInfo: userInfo) | |||
| // Change this to your preferred presentation option | |||
| completionHandler([[.banner, .list, .sound]]) | |||
| } | |||
| func userNotificationCenter(_ center: UNUserNotificationCenter, | |||
| didReceive response: UNNotificationResponse, | |||
| withCompletionHandler completionHandler: @escaping () -> Void) { | |||
| let userInfo = response.notification.request.content.userInfo | |||
| // Print message ID. | |||
| if let messageID = userInfo[gcmMessageIDKey] { | |||
| print("Message ID 4: \(messageID)") | |||
| } | |||
| // With swizzling disabled you must let Messaging know about the message, for Analytics | |||
| Messaging.messaging().appDidReceiveMessage(userInfo) | |||
| // Print full message. | |||
| print("push userInfo 4:", userInfo) | |||
| sendPushToWebView(userInfo: userInfo) | |||
| completionHandler() | |||
| } | |||
| } | |||
| // [END ios_10_message_handling] | |||
| extension AppDelegate : MessagingDelegate { | |||
| // [START refresh_token] | |||
| func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { | |||
| print("Firebase registration token: \(String(describing: fcmToken))") | |||
| let dataDict:[String: String] = ["token": fcmToken ?? ""] | |||
| NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict) | |||
| handleFCMToken() | |||
| // TODO: If necessary send token to application server. | |||
| // Note: This callback is fired at each app startup and whenever a new token is generated. | |||
| } | |||
| // [END refresh_token] | |||
| } | |||
| @ -0,0 +1,224 @@ | |||
| { | |||
| "images" : [ | |||
| { | |||
| "filename" : "40.png", | |||
| "idiom" : "iphone", | |||
| "scale" : "2x", | |||
| "size" : "20x20" | |||
| }, | |||
| { | |||
| "filename" : "60.png", | |||
| "idiom" : "iphone", | |||
| "scale" : "3x", | |||
| "size" : "20x20" | |||
| }, | |||
| { | |||
| "filename" : "29.png", | |||
| "idiom" : "iphone", | |||
| "scale" : "1x", | |||
| "size" : "29x29" | |||
| }, | |||
| { | |||
| "filename" : "58.png", | |||
| "idiom" : "iphone", | |||
| "scale" : "2x", | |||
| "size" : "29x29" | |||
| }, | |||
| { | |||
| "filename" : "87.png", | |||
| "idiom" : "iphone", | |||
| "scale" : "3x", | |||
| "size" : "29x29" | |||
| }, | |||
| { | |||
| "filename" : "80.png", | |||
| "idiom" : "iphone", | |||
| "scale" : "2x", | |||
| "size" : "40x40" | |||
| }, | |||
| { | |||
| "filename" : "120.png", | |||
| "idiom" : "iphone", | |||
| "scale" : "3x", | |||
| "size" : "40x40" | |||
| }, | |||
| { | |||
| "filename" : "57.png", | |||
| "idiom" : "iphone", | |||
| "scale" : "1x", | |||
| "size" : "57x57" | |||
| }, | |||
| { | |||
| "filename" : "114.png", | |||
| "idiom" : "iphone", | |||
| "scale" : "2x", | |||
| "size" : "57x57" | |||
| }, | |||
| { | |||
| "filename" : "120.png", | |||
| "idiom" : "iphone", | |||
| "scale" : "2x", | |||
| "size" : "60x60" | |||
| }, | |||
| { | |||
| "filename" : "180.png", | |||
| "idiom" : "iphone", | |||
| "scale" : "3x", | |||
| "size" : "60x60" | |||
| }, | |||
| { | |||
| "filename" : "20.png", | |||
| "idiom" : "ipad", | |||
| "scale" : "1x", | |||
| "size" : "20x20" | |||
| }, | |||
| { | |||
| "filename" : "40.png", | |||
| "idiom" : "ipad", | |||
| "scale" : "2x", | |||
| "size" : "20x20" | |||
| }, | |||
| { | |||
| "filename" : "29.png", | |||
| "idiom" : "ipad", | |||
| "scale" : "1x", | |||
| "size" : "29x29" | |||
| }, | |||
| { | |||
| "filename" : "58.png", | |||
| "idiom" : "ipad", | |||
| "scale" : "2x", | |||
| "size" : "29x29" | |||
| }, | |||
| { | |||
| "filename" : "40.png", | |||
| "idiom" : "ipad", | |||
| "scale" : "1x", | |||
| "size" : "40x40" | |||
| }, | |||
| { | |||
| "filename" : "80.png", | |||
| "idiom" : "ipad", | |||
| "scale" : "2x", | |||
| "size" : "40x40" | |||
| }, | |||
| { | |||
| "filename" : "50.png", | |||
| "idiom" : "ipad", | |||
| "scale" : "1x", | |||
| "size" : "50x50" | |||
| }, | |||
| { | |||
| "filename" : "100.png", | |||
| "idiom" : "ipad", | |||
| "scale" : "2x", | |||
| "size" : "50x50" | |||
| }, | |||
| { | |||
| "filename" : "72.png", | |||
| "idiom" : "ipad", | |||
| "scale" : "1x", | |||
| "size" : "72x72" | |||
| }, | |||
| { | |||
| "filename" : "144.png", | |||
| "idiom" : "ipad", | |||
| "scale" : "2x", | |||
| "size" : "72x72" | |||
| }, | |||
| { | |||
| "filename" : "76.png", | |||
| "idiom" : "ipad", | |||
| "scale" : "1x", | |||
| "size" : "76x76" | |||
| }, | |||
| { | |||
| "filename" : "152.png", | |||
| "idiom" : "ipad", | |||
| "scale" : "2x", | |||
| "size" : "76x76" | |||
| }, | |||
| { | |||
| "filename" : "167.png", | |||
| "idiom" : "ipad", | |||
| "scale" : "2x", | |||
| "size" : "83.5x83.5" | |||
| }, | |||
| { | |||
| "filename" : "1024.png", | |||
| "idiom" : "ios-marketing", | |||
| "scale" : "1x", | |||
| "size" : "1024x1024" | |||
| }, | |||
| { | |||
| "filename" : "AppIcon-16.png", | |||
| "idiom" : "mac", | |||
| "scale" : "1x", | |||
| "size" : "16x16" | |||
| }, | |||
| { | |||
| "filename" : "AppIcon-16@2x.png", | |||
| "idiom" : "mac", | |||
| "scale" : "2x", | |||
| "size" : "16x16" | |||
| }, | |||
| { | |||
| "filename" : "AppIcon-32.png", | |||
| "idiom" : "mac", | |||
| "scale" : "1x", | |||
| "size" : "32x32" | |||
| }, | |||
| { | |||
| "filename" : "AppIcon-32@2x.png", | |||
| "idiom" : "mac", | |||
| "scale" : "2x", | |||
| "size" : "32x32" | |||
| }, | |||
| { | |||
| "filename" : "AppIcon-128.png", | |||
| "idiom" : "mac", | |||
| "scale" : "1x", | |||
| "size" : "128x128" | |||
| }, | |||
| { | |||
| "filename" : "AppIcon-128@2x.png", | |||
| "idiom" : "mac", | |||
| "scale" : "2x", | |||
| "size" : "128x128" | |||
| }, | |||
| { | |||
| "filename" : "AppIcon-256.png", | |||
| "idiom" : "mac", | |||
| "scale" : "1x", | |||
| "size" : "256x256" | |||
| }, | |||
| { | |||
| "filename" : "AppIcon-256@2x.png", | |||
| "idiom" : "mac", | |||
| "scale" : "2x", | |||
| "size" : "256x256" | |||
| }, | |||
| { | |||
| "filename" : "AppIcon-512.png", | |||
| "idiom" : "mac", | |||
| "scale" : "1x", | |||
| "size" : "512x512" | |||
| }, | |||
| { | |||
| "filename" : "AppIcon-512@2x.png", | |||
| "idiom" : "mac", | |||
| "scale" : "2x", | |||
| "size" : "512x512" | |||
| }, | |||
| { | |||
| "filename" : "192.png", | |||
| "idiom" : "mac", | |||
| "scale" : "1x", | |||
| "size" : "192x192" | |||
| } | |||
| ], | |||
| "info" : { | |||
| "author" : "xcode", | |||
| "version" : 1 | |||
| } | |||
| } | |||
| @ -0,0 +1,9 @@ | |||
| { | |||
| "info" : { | |||
| "author" : "xcode", | |||
| "version" : 1 | |||
| }, | |||
| "properties" : { | |||
| "compression-type" : "gpu-optimized-smallest" | |||
| } | |||
| } | |||
| @ -0,0 +1,23 @@ | |||
| { | |||
| "images" : [ | |||
| { | |||
| "filename" : "1080.png", | |||
| "idiom" : "universal", | |||
| "scale" : "1x" | |||
| }, | |||
| { | |||
| "filename" : "1080@2x.png", | |||
| "idiom" : "universal", | |||
| "scale" : "2x" | |||
| }, | |||
| { | |||
| "filename" : "1080@3x.png", | |||
| "idiom" : "universal", | |||
| "scale" : "3x" | |||
| } | |||
| ], | |||
| "info" : { | |||
| "author" : "xcode", | |||
| "version" : 1 | |||
| } | |||
| } | |||
| @ -0,0 +1,23 @@ | |||
| { | |||
| "images" : [ | |||
| { | |||
| "filename" : "splash-screen-logo.png", | |||
| "idiom" : "universal", | |||
| "scale" : "1x" | |||
| }, | |||
| { | |||
| "filename" : "splash-screen-logo@2x.png", | |||
| "idiom" : "universal", | |||
| "scale" : "2x" | |||
| }, | |||
| { | |||
| "filename" : "splash-screen-logo@3x.png", | |||
| "idiom" : "universal", | |||
| "scale" : "3x" | |||
| } | |||
| ], | |||
| "info" : { | |||
| "author" : "xcode", | |||
| "version" : 1 | |||
| } | |||
| } | |||
| @ -0,0 +1,50 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> | |||
| <device id="retina6_0" orientation="portrait" appearance="light"/> | |||
| <dependencies> | |||
| <deployment identifier="iOS"/> | |||
| <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/> | |||
| <capability name="Safe area layout guides" minToolsVersion="9.0"/> | |||
| <capability name="System colors in document resources" minToolsVersion="11.0"/> | |||
| <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> | |||
| </dependencies> | |||
| <scenes> | |||
| <!--View Controller--> | |||
| <scene sceneID="EHf-IW-A2E"> | |||
| <objects> | |||
| <viewController id="01J-lp-oVM" sceneMemberID="viewController"> | |||
| <view key="view" contentMode="scaleToFill" id="4mO-e4-REQ"> | |||
| <rect key="frame" x="0.0" y="0.0" width="390" height="844"/> | |||
| <autoresizingMask key="autoresizingMask"/> | |||
| <subviews> | |||
| <imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="1000" verticalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" image="splash-screen-logo" translatesAutoresizingMaskIntoConstraints="NO" id="I2s-HW-Q4d"> | |||
| <rect key="frame" x="0.0" y="0.0" width="390" height="844"/> | |||
| <color key="tintColor" systemColor="secondarySystemFillColor"/> | |||
| </imageView> | |||
| </subviews> | |||
| <viewLayoutGuide key="safeArea" id="XpK-Bq-A7U"/> | |||
| <color key="backgroundColor" systemColor="systemBackgroundColor"/> | |||
| <constraints> | |||
| <constraint firstItem="I2s-HW-Q4d" firstAttribute="centerY" secondItem="4mO-e4-REQ" secondAttribute="centerY" id="4kv-Qc-mPU"/> | |||
| <constraint firstItem="I2s-HW-Q4d" firstAttribute="centerX" secondItem="4mO-e4-REQ" secondAttribute="centerX" id="6Z0-rS-c8Q"/> | |||
| <constraint firstItem="XpK-Bq-A7U" firstAttribute="trailing" secondItem="I2s-HW-Q4d" secondAttribute="trailing" id="P0W-Yo-EXM"/> | |||
| <constraint firstItem="I2s-HW-Q4d" firstAttribute="leading" secondItem="XpK-Bq-A7U" secondAttribute="leading" id="uVQ-4m-DsE"/> | |||
| <constraint firstItem="I2s-HW-Q4d" firstAttribute="top" secondItem="4mO-e4-REQ" secondAttribute="top" id="wM3-pS-BxC"/> | |||
| </constraints> | |||
| </view> | |||
| </viewController> | |||
| <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/> | |||
| </objects> | |||
| <point key="canvasLocation" x="50.724637681159422" y="374.33035714285711"/> | |||
| </scene> | |||
| </scenes> | |||
| <resources> | |||
| <image name="splash-screen-logo" width="170.66667175292969" height="360"/> | |||
| <systemColor name="secondarySystemFillColor"> | |||
| <color red="0.47058823529999999" green="0.47058823529999999" blue="0.50196078430000002" alpha="0.16" colorSpace="custom" customColorSpace="sRGB"/> | |||
| </systemColor> | |||
| <systemColor name="systemBackgroundColor"> | |||
| <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> | |||
| </systemColor> | |||
| </resources> | |||
| </document> | |||
| @ -0,0 +1,86 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> | |||
| <device id="retina5_9" orientation="portrait" appearance="light"/> | |||
| <dependencies> | |||
| <deployment identifier="iOS"/> | |||
| <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/> | |||
| <capability name="Safe area layout guides" minToolsVersion="9.0"/> | |||
| <capability name="System colors in document resources" minToolsVersion="11.0"/> | |||
| <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> | |||
| </dependencies> | |||
| <scenes> | |||
| <!--View Controller--> | |||
| <scene sceneID="tne-QT-ifu"> | |||
| <objects> | |||
| <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="Nivesh" customModuleProvider="target" sceneMemberID="viewController"> | |||
| <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> | |||
| <rect key="frame" x="0.0" y="0.0" width="375" height="812"/> | |||
| <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> | |||
| <subviews> | |||
| <view contentMode="scaleToFill" id="PHY-vp-dMl" userLabel="Webview View"> | |||
| <rect key="frame" x="0.0" y="0.0" width="375" height="812"/> | |||
| <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> | |||
| <subviews> | |||
| <view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="p0s-Fg-eGP" userLabel="Splash Background"> | |||
| <rect key="frame" x="0.0" y="0.0" width="375" height="812"/> | |||
| <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> | |||
| <subviews> | |||
| <view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DIO-mU-n27" userLabel="Loading View"> | |||
| <rect key="frame" x="88" y="306" width="200" height="200"/> | |||
| <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/> | |||
| <subviews> | |||
| <imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="n-logo" translatesAutoresizingMaskIntoConstraints="NO" id="4oa-LZ-pgs"> | |||
| <rect key="frame" x="68" y="68" width="64" height="64"/> | |||
| <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/> | |||
| <color key="tintColor" systemColor="secondarySystemFillColor"/> | |||
| <rect key="contentStretch" x="0.0" y="0.0" width="0.0" height="0.0"/> | |||
| </imageView> | |||
| <progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" progress="0.10000000000000001" id="xSD-dq-HF9"> | |||
| <rect key="frame" x="50" y="146" width="100" height="15"/> | |||
| <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/> | |||
| <color key="backgroundColor" systemColor="secondarySystemFillColor"/> | |||
| <color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | |||
| </progressView> | |||
| <imageView hidden="YES" opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="wifi.slash" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="TpV-I7-c6z"> | |||
| <rect key="frame" x="85" y="159.33333333333314" width="31.999999999999886" height="30.000000000000085"/> | |||
| <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> | |||
| <color key="tintColor" systemColor="secondaryLabelColor"/> | |||
| </imageView> | |||
| </subviews> | |||
| <viewLayoutGuide key="safeArea" id="a0B-Gx-0cO"/> | |||
| <rect key="contentStretch" x="0.0" y="0.0" width="0.0" height="0.0"/> | |||
| </view> | |||
| </subviews> | |||
| </view> | |||
| </subviews> | |||
| </view> | |||
| </subviews> | |||
| <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/> | |||
| <color key="backgroundColor" systemColor="systemBackgroundColor"/> | |||
| </view> | |||
| <connections> | |||
| <outlet property="connectionProblemView" destination="TpV-I7-c6z" id="76F-WR-UnJ"/> | |||
| <outlet property="loadingView" destination="DIO-mU-n27" id="Wlk-Yd-6b1"/> | |||
| <outlet property="progressView" destination="xSD-dq-HF9" id="0jL-XR-Xwq"/> | |||
| <outlet property="webviewView" destination="PHY-vp-dMl" id="qhH-E4-3lf"/> | |||
| </connections> | |||
| </viewController> | |||
| <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> | |||
| </objects> | |||
| <point key="canvasLocation" x="1036.9230769230769" y="135.07109004739337"/> | |||
| </scene> | |||
| </scenes> | |||
| <resources> | |||
| <image name="n-logo" width="360" height="360"/> | |||
| <image name="wifi.slash" catalog="system" width="128" height="111"/> | |||
| <systemColor name="secondaryLabelColor"> | |||
| <color red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> | |||
| </systemColor> | |||
| <systemColor name="secondarySystemFillColor"> | |||
| <color red="0.47058823529999999" green="0.47058823529999999" blue="0.50196078430000002" alpha="0.16" colorSpace="custom" customColorSpace="sRGB"/> | |||
| </systemColor> | |||
| <systemColor name="systemBackgroundColor"> | |||
| <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> | |||
| </systemColor> | |||
| </resources> | |||
| </document> | |||
| @ -0,0 +1 @@ | |||
| /GoogleService-Info.plist | |||
| @ -0,0 +1,27 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||
| <plist version="1.0"> | |||
| <dict> | |||
| <key>aps-environment</key> | |||
| <string>production</string> | |||
| <key>com.apple.developer.associated-domains</key> | |||
| <array> | |||
| <string>applinks:app.nivesh.com</string> | |||
| <string>webcredentials:app.nivesh.com</string> | |||
| </array> | |||
| <key>com.apple.security.app-sandbox</key> | |||
| <true/> | |||
| <key>com.apple.security.device.audio-input</key> | |||
| <true/> | |||
| <key>com.apple.security.device.camera</key> | |||
| <true/> | |||
| <key>com.apple.security.files.user-selected.read-write</key> | |||
| <true/> | |||
| <key>com.apple.security.network.client</key> | |||
| <true/> | |||
| <key>com.apple.security.personal-information.location</key> | |||
| <true/> | |||
| <key>com.apple.security.print</key> | |||
| <true/> | |||
| </dict> | |||
| </plist> | |||
| @ -0,0 +1,124 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||
| <plist version="1.0"> | |||
| <dict> | |||
| <key>BGTaskSchedulerPermittedIdentifiers</key> | |||
| <array> | |||
| <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | |||
| </array> | |||
| <key>CFBundleDevelopmentRegion</key> | |||
| <string>$(DEVELOPMENT_LANGUAGE)</string> | |||
| <key>CFBundleDisplayName</key> | |||
| <string>Nivesh</string> | |||
| <key>CFBundleExecutable</key> | |||
| <string>$(EXECUTABLE_NAME)</string> | |||
| <key>CFBundleIdentifier</key> | |||
| <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | |||
| <key>CFBundleInfoDictionaryVersion</key> | |||
| <string>6.0</string> | |||
| <key>CFBundleName</key> | |||
| <string>$(PRODUCT_NAME)</string> | |||
| <key>CFBundlePackageType</key> | |||
| <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> | |||
| <key>CFBundleShortVersionString</key> | |||
| <string>$(MARKETING_VERSION)</string> | |||
| <key>CFBundleURLTypes</key> | |||
| <array> | |||
| <dict> | |||
| <key>CFBundleTypeRole</key> | |||
| <string>Editor</string> | |||
| <key>CFBundleURLName</key> | |||
| <string>com.nivesh.app</string> | |||
| <key>CFBundleURLSchemes</key> | |||
| <array> | |||
| <string>app</string> | |||
| </array> | |||
| </dict> | |||
| </array> | |||
| <key>CFBundleVersion</key> | |||
| <string>$(CURRENT_PROJECT_VERSION)</string> | |||
| <key>ITSAppUsesNonExemptEncryption</key> | |||
| <false/> | |||
| <key>LSApplicationCategoryType</key> | |||
| <string></string> | |||
| <key>LSRequiresIPhoneOS</key> | |||
| <true/> | |||
| <key>NSAppTransportSecurity</key> | |||
| <dict> | |||
| <key>NSAllowsArbitraryLoads</key> | |||
| <true/> | |||
| </dict> | |||
| <key>NSCameraUsageDescription</key> | |||
| <string>App needs to capture user document for KYC mandated by Indian regulation (SEBI)</string> | |||
| <key>NSLocationWhenInUseUsageDescription</key> | |||
| <string>Track current location by user request</string> | |||
| <key>NSMicrophoneUsageDescription</key> | |||
| <string>Capture Audio by user request</string> | |||
| <key>UIApplicationSceneManifest</key> | |||
| <dict> | |||
| <key>UIApplicationSupportsMultipleScenes</key> | |||
| <false/> | |||
| <key>UISceneConfigurations</key> | |||
| <dict> | |||
| <key>UIWindowSceneSessionRoleApplication</key> | |||
| <array> | |||
| <dict> | |||
| <key>UISceneConfigurationName</key> | |||
| <string>Default Configuration</string> | |||
| <key>UISceneDelegateClassName</key> | |||
| <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string> | |||
| <key>UISceneStoryboardFile</key> | |||
| <string>Main</string> | |||
| </dict> | |||
| </array> | |||
| </dict> | |||
| </dict> | |||
| <key>UIBackgroundModes</key> | |||
| <array> | |||
| <string>processing</string> | |||
| <string>remote-notification</string> | |||
| </array> | |||
| <key>UILaunchStoryboardName</key> | |||
| <string>LaunchScreen</string> | |||
| <key>UIMainStoryboardFile</key> | |||
| <string>Main</string> | |||
| <key>UIRequiredDeviceCapabilities</key> | |||
| <array> | |||
| <string>armv7</string> | |||
| </array> | |||
| <key>UIStatusBarStyle</key> | |||
| <string>UIStatusBarStyleDefault</string> | |||
| <key>UISupportedInterfaceOrientations</key> | |||
| <array> | |||
| <string>UIInterfaceOrientationPortrait</string> | |||
| <string>UIInterfaceOrientationLandscapeLeft</string> | |||
| <string>UIInterfaceOrientationLandscapeRight</string> | |||
| <string>UIInterfaceOrientationPortraitUpsideDown</string> | |||
| </array> | |||
| <key>UISupportedInterfaceOrientations~ipad</key> | |||
| <array> | |||
| <string>UIInterfaceOrientationPortrait</string> | |||
| <string>UIInterfaceOrientationPortraitUpsideDown</string> | |||
| <string>UIInterfaceOrientationLandscapeLeft</string> | |||
| <string>UIInterfaceOrientationLandscapeRight</string> | |||
| </array> | |||
| <key>UIViewControllerBasedStatusBarAppearance</key> | |||
| <true/> | |||
| <key>WKAppBoundDomains</key> | |||
| <array> | |||
| <string>sandbox.nivesh.com</string> | |||
| </array> | |||
| <key>branch_key</key> | |||
| <dict> | |||
| <key>live</key> | |||
| <string>key_live_ihFWcIYhk9JEbG6TR0dOSbkoDydh2HKF</string> | |||
| </dict> | |||
| <key>branch_universal_link_domains</key> | |||
| <dict> | |||
| <key>Item 0</key> | |||
| <string>nivesh.app.link</string> | |||
| <key>Item 1</key> | |||
| <string>nivesh-alternate.app.link</string> | |||
| </dict> | |||
| </dict> | |||
| </plist> | |||
| @ -0,0 +1,29 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||
| <plist version="1.0"> | |||
| <dict> | |||
| <key>aps-environment</key> | |||
| <string>production</string> | |||
| <key>com.apple.developer.associated-domains</key> | |||
| <array> | |||
| <string>applinks:app.nivesh.com</string> | |||
| <string>webcredentials:app.nivesh.com</string> | |||
| <string>nivesh.app.link</string> | |||
| <string>nivesh-alternate.app.link</string> | |||
| </array> | |||
| <key>com.apple.security.app-sandbox</key> | |||
| <true/> | |||
| <key>com.apple.security.device.audio-input</key> | |||
| <true/> | |||
| <key>com.apple.security.device.camera</key> | |||
| <true/> | |||
| <key>com.apple.security.files.user-selected.read-write</key> | |||
| <true/> | |||
| <key>com.apple.security.network.client</key> | |||
| <true/> | |||
| <key>com.apple.security.personal-information.location</key> | |||
| <true/> | |||
| <key>com.apple.security.print</key> | |||
| <true/> | |||
| </dict> | |||
| </plist> | |||
| @ -0,0 +1,20 @@ | |||
| import UIKit | |||
| import WebKit | |||
| func printView(webView: WKWebView){ | |||
| let printController = UIPrintInteractionController.shared | |||
| let printInfo = UIPrintInfo(dictionary:nil) | |||
| printInfo.outputType = UIPrintInfo.OutputType.general | |||
| printInfo.jobName = (webView.url?.absoluteString)! | |||
| printInfo.duplex = UIPrintInfo.Duplex.none | |||
| printInfo.orientation = UIPrintInfo.Orientation.portrait | |||
| printController.printPageRenderer = UIPrintPageRenderer() | |||
| printController.printPageRenderer?.addPrintFormatter(webView.viewPrintFormatter(), startingAtPageAt: 0) | |||
| printController.printInfo = printInfo | |||
| printController.showsNumberOfCopies = true | |||
| printController.present(animated: true) | |||
| } | |||
| @ -0,0 +1,173 @@ | |||
| import WebKit | |||
| import FirebaseMessaging | |||
| class SubscribeMessage { | |||
| var topic = "" | |||
| var eventValue = "" | |||
| var unsubscribe = false | |||
| struct Keys { | |||
| static var TOPIC = "topic" | |||
| static var UNSUBSCRIBE = "unsubscribe" | |||
| static var EVENTVALUE = "eventValue" | |||
| } | |||
| convenience init(dict: Dictionary<String,Any>) { | |||
| self.init() | |||
| if let topic = dict[Keys.TOPIC] as? String { | |||
| self.topic = topic | |||
| } | |||
| if let unsubscribe = dict[Keys.UNSUBSCRIBE] as? Bool { | |||
| self.unsubscribe = unsubscribe | |||
| } | |||
| if let eventValue = dict[Keys.EVENTVALUE] as? String { | |||
| self.eventValue = eventValue | |||
| } | |||
| } | |||
| } | |||
| func handleSubscribeTouch(message: WKScriptMessage) { | |||
| // [START subscribe_topic] | |||
| let subscribeMessages = parseSubscribeMessage(message: message) | |||
| if (subscribeMessages.count > 0){ | |||
| let _message = subscribeMessages[0] | |||
| if (_message.unsubscribe) { | |||
| Messaging.messaging().unsubscribe(fromTopic: _message.topic) { error in } | |||
| } | |||
| else { | |||
| Messaging.messaging().subscribe(toTopic: _message.topic) { error in } | |||
| } | |||
| } | |||
| // [END subscribe_topic] | |||
| } | |||
| func parseSubscribeMessage(message: WKScriptMessage) -> [SubscribeMessage] { | |||
| var subscribeMessages = [SubscribeMessage]() | |||
| if let objStr = message.body as? String { | |||
| let data: Data = objStr.data(using: .utf8)! | |||
| do { | |||
| let jsObj = try JSONSerialization.jsonObject(with: data, options: .init(rawValue: 0)) | |||
| if let jsonObjDict = jsObj as? Dictionary<String, Any> { | |||
| let subscribeMessage = SubscribeMessage(dict: jsonObjDict) | |||
| subscribeMessages.append(subscribeMessage) | |||
| } else if let jsonArr = jsObj as? [Dictionary<String, Any>] { | |||
| for jsonObj in jsonArr { | |||
| let sMessage = SubscribeMessage(dict: jsonObj) | |||
| subscribeMessages.append(sMessage) | |||
| } | |||
| } | |||
| } catch _ { | |||
| } | |||
| } | |||
| return subscribeMessages | |||
| } | |||
| func returnPermissionResult(isGranted: Bool){ | |||
| DispatchQueue.main.async(execute: { | |||
| if (isGranted){ | |||
| Nivesh.webView.evaluateJavaScript("this.dispatchEvent(new CustomEvent('push-permission-request', { detail: 'granted' }))") | |||
| } | |||
| else { | |||
| Nivesh.webView.evaluateJavaScript("this.dispatchEvent(new CustomEvent('push-permission-request', { detail: 'denied' }))") | |||
| } | |||
| }) | |||
| } | |||
| func returnPermissionState(state: String){ | |||
| DispatchQueue.main.async(execute: { | |||
| Nivesh.webView.evaluateJavaScript("this.dispatchEvent(new CustomEvent('push-permission-state', { detail: '\(state)' }))") | |||
| }) | |||
| } | |||
| func handlePushPermission() { | |||
| UNUserNotificationCenter.current().getNotificationSettings () { settings in | |||
| switch settings.authorizationStatus { | |||
| case .notDetermined: | |||
| let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] | |||
| UNUserNotificationCenter.current().requestAuthorization( | |||
| options: authOptions, | |||
| completionHandler: { (success, error) in | |||
| if error == nil { | |||
| if success == true { | |||
| returnPermissionResult(isGranted: true) | |||
| DispatchQueue.main.async { | |||
| UIApplication.shared.registerForRemoteNotifications() | |||
| } | |||
| } | |||
| else { | |||
| returnPermissionResult(isGranted: false) | |||
| } | |||
| } | |||
| else { | |||
| returnPermissionResult(isGranted: false) | |||
| } | |||
| } | |||
| ) | |||
| case .denied: | |||
| returnPermissionResult(isGranted: false) | |||
| case .authorized, .ephemeral, .provisional: | |||
| returnPermissionResult(isGranted: true) | |||
| @unknown default: | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| func handlePushState() { | |||
| UNUserNotificationCenter.current().getNotificationSettings () { settings in | |||
| switch settings.authorizationStatus { | |||
| case .notDetermined: | |||
| returnPermissionState(state: "notDetermined") | |||
| case .denied: | |||
| returnPermissionState(state: "denied") | |||
| case .authorized: | |||
| returnPermissionState(state: "authorized") | |||
| case .ephemeral: | |||
| returnPermissionState(state: "ephemeral") | |||
| case .provisional: | |||
| returnPermissionState(state: "provisional") | |||
| @unknown default: | |||
| returnPermissionState(state: "unknown") | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| func checkViewAndEvaluate(event: String, detail: String) { | |||
| if (!Nivesh.webView.isHidden && !Nivesh.webView.isLoading ) { | |||
| DispatchQueue.main.async(execute: { | |||
| Nivesh.webView.evaluateJavaScript("this.dispatchEvent(new CustomEvent('\(event)', { detail: \(detail) }))") | |||
| }) | |||
| } | |||
| else { | |||
| DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { | |||
| checkViewAndEvaluate(event: event, detail: detail) | |||
| } | |||
| } | |||
| } | |||
| func handleFCMToken(){ | |||
| DispatchQueue.main.async(execute: { | |||
| Messaging.messaging().token { token, error in | |||
| if let error = error { | |||
| print("Error fetching FCM registration token: \(error)") | |||
| checkViewAndEvaluate(event: "push-token", detail: "ERROR GET TOKEN") | |||
| } else if let token = token { | |||
| print("FCM registration token: \(token)") | |||
| checkViewAndEvaluate(event: "push-token", detail: "'\(token)'") | |||
| } | |||
| } | |||
| }) | |||
| } | |||
| func sendPushToWebView(userInfo: [AnyHashable: Any]){ | |||
| var json = ""; | |||
| do { | |||
| let jsonData = try JSONSerialization.data(withJSONObject: userInfo) | |||
| json = String(data: jsonData, encoding: .utf8)! | |||
| } catch { | |||
| print("ERROR: userInfo parsing problem") | |||
| return | |||
| } | |||
| checkViewAndEvaluate(event: "push-notification", detail: json) | |||
| } | |||
| @ -0,0 +1,111 @@ | |||
| import UIKit | |||
| @available(iOS 13.0, *) | |||
| class SceneDelegate: UIResponder, UIWindowSceneDelegate { | |||
| var window: UIWindow? | |||
| // If our app is launched with a universal link, we'll store it in this variable | |||
| static var universalLinkToLaunch: URL? = nil; | |||
| static var shortcutLinkToLaunch: URL? = nil | |||
| // This function is called when your app launches. | |||
| // Check to see if we were launched via a universal link or a shortcut. | |||
| func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { | |||
| // See if our app is being launched via universal link. | |||
| // If so, store that link so we can navigate to it once our webView is initialized. | |||
| for userActivity in connectionOptions.userActivities { | |||
| if let universalLink = userActivity.webpageURL { | |||
| SceneDelegate.universalLinkToLaunch = universalLink; | |||
| break | |||
| } | |||
| } | |||
| // See if we were launched via shortcut | |||
| if let shortcutUrl = connectionOptions.shortcutItem?.type { | |||
| SceneDelegate.shortcutLinkToLaunch = URL.init(string: shortcutUrl) | |||
| } | |||
| // See if we were launched via scheme URL | |||
| if let schemeUrl = connectionOptions.urlContexts.first?.url { | |||
| // Convert scheme://url to a https://url | |||
| var comps = URLComponents(url: schemeUrl, resolvingAgainstBaseURL: false) | |||
| comps?.scheme = "https" | |||
| if let url = comps?.url { | |||
| SceneDelegate.universalLinkToLaunch = url; | |||
| } | |||
| } | |||
| } | |||
| // This function is called when our app is already running and the user clicks a custom scheme URL | |||
| func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { | |||
| if let scheme = URLContexts.first?.url { | |||
| // Convert scheme://url to a https://url and navigate to it | |||
| var comps = URLComponents(url: scheme, resolvingAgainstBaseURL: false) | |||
| comps?.scheme = "https" | |||
| if let url = comps?.url { | |||
| // Handle it inside our web view in a SPA-friendly way. | |||
| Nivesh.webView.evaluateJavaScript("location.href = '\(url)'") | |||
| } | |||
| } | |||
| } | |||
| // This function is called when our app is already running and the user clicks a universal link. | |||
| func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { | |||
| // Handle universal links into our app when the app is already running. | |||
| // This allows your PWA to open links to your domain, rather than opening in a browser tab. | |||
| // For more info about universal links, see https://developer.apple.com/documentation/xcode/supporting-universal-links-in-your-app | |||
| // Ensure we're trying to launch a link. | |||
| guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, | |||
| let universalLink = userActivity.webpageURL else { | |||
| return | |||
| } | |||
| // Handle it inside our web view in a SPA-friendly way. | |||
| Nivesh.webView.evaluateJavaScript("location.href = '\(universalLink)'") | |||
| } | |||
| // This function is called if our app is already loaded and the user activates the app via shortcut | |||
| func windowScene(_ windowScene: UIWindowScene, | |||
| performActionFor shortcutItem: UIApplicationShortcutItem, | |||
| completionHandler: @escaping (Bool) -> Void) { | |||
| if let shortcutUrl = URL.init(string: shortcutItem.type) { | |||
| Nivesh.webView.evaluateJavaScript("location.href = '\(shortcutUrl)'"); | |||
| } | |||
| } | |||
| 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 neccessarily 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. | |||
| } | |||
| } | |||
| @ -0,0 +1,29 @@ | |||
| import WebKit | |||
| struct Cookie { | |||
| var name: String | |||
| var value: String | |||
| } | |||
| let gcmMessageIDKey = "00000000000" // update this with actual ID if using Firebase | |||
| // URL for first launch | |||
| let rootUrl = URL(string: "https://sandbox.nivesh.com")! | |||
| // allowed origin is for what we are sticking to pwa domain | |||
| // This should also appear in Info.plist | |||
| let allowedOrigins: [String] = ["sandbox.nivesh.com"] | |||
| // auth origins will open in modal and show toolbar for back into the main origin. | |||
| // These should also appear in Info.plist | |||
| let authOrigins: [String] = [] | |||
| // allowedOrigins + authOrigins <= 10 | |||
| let platformCookie = Cookie(name: "app-platform", value: "iOS App Store") | |||
| // UI options | |||
| let displayMode = "standalone" // standalone / fullscreen. | |||
| let adaptiveUIStyle = true // iOS 15+ only. Change app theme on the fly to dark/light related to WebView background color. | |||
| let overrideStatusBar = false // iOS 13-14 only. if you don't support dark/light system theme. | |||
| let statusBarTheme = "dark" // dark / light, related to override option. | |||
| let pullToRefresh = true // Enable/disable pull down to refresh page | |||
| @ -0,0 +1,249 @@ | |||
| import UIKit | |||
| import WebKit | |||
| var webView: WKWebView! = nil | |||
| class ViewController: UIViewController, WKNavigationDelegate, UIDocumentInteractionControllerDelegate { | |||
| var documentController: UIDocumentInteractionController? | |||
| func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController { | |||
| return self | |||
| } | |||
| @IBOutlet weak var loadingView: UIView! | |||
| @IBOutlet weak var progressView: UIProgressView! | |||
| @IBOutlet weak var connectionProblemView: UIImageView! | |||
| @IBOutlet weak var webviewView: UIView! | |||
| var toolbarView: UIToolbar! | |||
| var htmlIsLoaded = false; | |||
| private var themeObservation: NSKeyValueObservation? | |||
| var currentWebViewTheme: UIUserInterfaceStyle = .unspecified | |||
| override var preferredStatusBarStyle : UIStatusBarStyle { | |||
| if #available(iOS 13, *), overrideStatusBar{ | |||
| if #available(iOS 15, *) { | |||
| return .default | |||
| } else { | |||
| return statusBarTheme == "dark" ? .lightContent : .darkContent | |||
| } | |||
| } | |||
| return .default | |||
| } | |||
| override func viewDidLoad() { | |||
| super.viewDidLoad() | |||
| initWebView() | |||
| initToolbarView() | |||
| loadRootUrl() | |||
| NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification , object: nil) | |||
| } | |||
| override func viewDidLayoutSubviews() { | |||
| super.viewDidLayoutSubviews() | |||
| Nivesh.webView.frame = calcWebviewFrame(webviewView: webviewView, toolbarView: nil) | |||
| } | |||
| @objc func keyboardWillHide(_ notification: NSNotification) { | |||
| Nivesh.webView.setNeedsLayout() | |||
| } | |||
| func initWebView() { | |||
| Nivesh.webView = createWebView(container: webviewView, WKSMH: self, WKND: self, NSO: self, VC: self) | |||
| webviewView.addSubview(Nivesh.webView); | |||
| Nivesh.webView.uiDelegate = self; | |||
| Nivesh.webView.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil) | |||
| if(pullToRefresh){ | |||
| let refreshControl = UIRefreshControl() | |||
| refreshControl.addTarget(self, action: #selector(refreshWebView(_:)), for: UIControl.Event.valueChanged) | |||
| Nivesh.webView.scrollView.addSubview(refreshControl) | |||
| Nivesh.webView.scrollView.bounces = true | |||
| } | |||
| if #available(iOS 15.0, *), adaptiveUIStyle { | |||
| themeObservation = Nivesh.webView.observe(\.underPageBackgroundColor) { [unowned self] webView, _ in | |||
| currentWebViewTheme = Nivesh.webView.underPageBackgroundColor.isLight() ?? true ? .light : .dark | |||
| self.overrideUIStyle() | |||
| } | |||
| } | |||
| } | |||
| @objc func refreshWebView(_ sender: UIRefreshControl) { | |||
| Nivesh.webView?.reload() | |||
| sender.endRefreshing() | |||
| } | |||
| func createToolbarView() -> UIToolbar{ | |||
| let winScene = UIApplication.shared.connectedScenes.first | |||
| let windowScene = winScene as! UIWindowScene | |||
| var statusBarHeight = windowScene.statusBarManager?.statusBarFrame.height ?? 60 | |||
| #if targetEnvironment(macCatalyst) | |||
| if (statusBarHeight == 0){ | |||
| statusBarHeight = 30 | |||
| } | |||
| #endif | |||
| let toolbarView = UIToolbar(frame: CGRect(x: 0, y: 0, width: webviewView.frame.width, height: 0)) | |||
| toolbarView.sizeToFit() | |||
| toolbarView.frame = CGRect(x: 0, y: 0, width: webviewView.frame.width, height: toolbarView.frame.height + statusBarHeight) | |||
| // toolbarView.autoresizingMask = [.flexibleTopMargin, .flexibleRightMargin, .flexibleWidth] | |||
| let flex = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) | |||
| let close = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(loadRootUrl)) | |||
| toolbarView.setItems([close,flex], animated: true) | |||
| toolbarView.isHidden = true | |||
| return toolbarView | |||
| } | |||
| func overrideUIStyle(toDefault: Bool = false) { | |||
| if #available(iOS 15.0, *), adaptiveUIStyle { | |||
| if (((htmlIsLoaded && !Nivesh.webView.isHidden) || toDefault) && self.currentWebViewTheme != .unspecified) { | |||
| UIApplication | |||
| .shared | |||
| .connectedScenes | |||
| .flatMap { ($0 as? UIWindowScene)?.windows ?? [] } | |||
| .first { $0.isKeyWindow }?.overrideUserInterfaceStyle = toDefault ? .unspecified : self.currentWebViewTheme; | |||
| } | |||
| } | |||
| } | |||
| func initToolbarView() { | |||
| toolbarView = createToolbarView() | |||
| webviewView.addSubview(toolbarView) | |||
| } | |||
| @objc func loadRootUrl() { | |||
| Nivesh.webView.load(URLRequest(url: SceneDelegate.universalLinkToLaunch ?? SceneDelegate.shortcutLinkToLaunch ?? rootUrl)) | |||
| } | |||
| func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!){ | |||
| htmlIsLoaded = true | |||
| self.setProgress(1.0, true) | |||
| self.animateConnectionProblem(false) | |||
| DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) { | |||
| Nivesh.webView.isHidden = false | |||
| self.loadingView.isHidden = true | |||
| self.setProgress(0.0, false) | |||
| self.overrideUIStyle() | |||
| } | |||
| } | |||
| func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { | |||
| htmlIsLoaded = false; | |||
| if (error as NSError)._code != (-999) { | |||
| self.overrideUIStyle(toDefault: true); | |||
| webView.isHidden = true; | |||
| loadingView.isHidden = false; | |||
| animateConnectionProblem(true); | |||
| setProgress(0.05, true); | |||
| DispatchQueue.main.asyncAfter(deadline: .now() + 3) { | |||
| self.setProgress(0.1, true); | |||
| DispatchQueue.main.asyncAfter(deadline: .now() + 3) { | |||
| self.loadRootUrl(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { | |||
| if (keyPath == #keyPath(WKWebView.estimatedProgress) && | |||
| Nivesh.webView.isLoading && | |||
| !self.loadingView.isHidden && | |||
| !self.htmlIsLoaded) { | |||
| var progress = Float(Nivesh.webView.estimatedProgress); | |||
| if (progress >= 0.8) { progress = 1.0; }; | |||
| if (progress >= 0.3) { self.animateConnectionProblem(false); } | |||
| self.setProgress(progress, true); | |||
| } | |||
| } | |||
| func setProgress(_ progress: Float, _ animated: Bool) { | |||
| self.progressView.setProgress(progress, animated: animated); | |||
| } | |||
| func animateConnectionProblem(_ show: Bool) { | |||
| if (show) { | |||
| self.connectionProblemView.isHidden = false; | |||
| self.connectionProblemView.alpha = 0 | |||
| UIView.animate(withDuration: 0.7, delay: 0, options: [.repeat, .autoreverse], animations: { | |||
| self.connectionProblemView.alpha = 1 | |||
| }) | |||
| } | |||
| else { | |||
| UIView.animate(withDuration: 0.3, delay: 0, options: [], animations: { | |||
| self.connectionProblemView.alpha = 0 // Here you will get the animation you want | |||
| }, completion: { _ in | |||
| self.connectionProblemView.isHidden = true; | |||
| self.connectionProblemView.layer.removeAllAnimations(); | |||
| }) | |||
| } | |||
| } | |||
| deinit { | |||
| Nivesh.webView.removeObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress)) | |||
| } | |||
| } | |||
| extension UIColor { | |||
| // Check if the color is light or dark, as defined by the injected lightness threshold. | |||
| // Some people report that 0.7 is best. I suggest to find out for yourself. | |||
| // A nil value is returned if the lightness couldn't be determined. | |||
| func isLight(threshold: Float = 0.5) -> Bool? { | |||
| let originalCGColor = self.cgColor | |||
| // Now we need to convert it to the RGB colorspace. UIColor.white / UIColor.black are greyscale and not RGB. | |||
| // If you don't do this then you will crash when accessing components index 2 below when evaluating greyscale colors. | |||
| let RGBCGColor = originalCGColor.converted(to: CGColorSpaceCreateDeviceRGB(), intent: .defaultIntent, options: nil) | |||
| guard let components = RGBCGColor?.components else { | |||
| return nil | |||
| } | |||
| guard components.count >= 3 else { | |||
| return nil | |||
| } | |||
| let brightness = Float(((components[0] * 299) + (components[1] * 587) + (components[2] * 114)) / 1000) | |||
| return (brightness > threshold) | |||
| } | |||
| } | |||
| extension ViewController: WKScriptMessageHandler { | |||
| func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { | |||
| if message.name == "print" { | |||
| printView(webView: Nivesh.webView) | |||
| } | |||
| if message.name == "push-subscribe" { | |||
| handleSubscribeTouch(message: message) | |||
| } | |||
| if message.name == "push-permission-request" { | |||
| handlePushPermission() | |||
| } | |||
| if message.name == "push-permission-state" { | |||
| handlePushState() | |||
| } | |||
| if message.name == "push-token" { | |||
| handleFCMToken() | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,406 @@ | |||
| import UIKit | |||
| import WebKit | |||
| import AuthenticationServices | |||
| import SafariServices | |||
| import FirebaseMessaging | |||
| func createWebView(container: UIView, WKSMH: WKScriptMessageHandler, WKND: WKNavigationDelegate, NSO: NSObject, VC: ViewController) -> WKWebView{ | |||
| let config = WKWebViewConfiguration() | |||
| let userContentController = WKUserContentController() | |||
| userContentController.add(WKSMH, name: "print") | |||
| userContentController.add(WKSMH, name: "push-subscribe") | |||
| userContentController.add(WKSMH, name: "push-permission-request") | |||
| userContentController.add(WKSMH, name: "push-permission-state") | |||
| userContentController.add(WKSMH, name: "push-token") | |||
| config.userContentController = userContentController | |||
| config.limitsNavigationsToAppBoundDomains = false; | |||
| config.allowsInlineMediaPlayback = true | |||
| config.preferences.javaScriptCanOpenWindowsAutomatically = true | |||
| config.preferences.setValue(true, forKey: "standalone") | |||
| let webView = WKWebView(frame: calcWebviewFrame(webviewView: container, toolbarView: nil), configuration: config) | |||
| setCustomCookie(webView: webView) | |||
| webView.autoresizingMask = [.flexibleWidth, .flexibleHeight] | |||
| webView.isHidden = true; | |||
| webView.navigationDelegate = WKND | |||
| webView.scrollView.bounces = false | |||
| webView.scrollView.contentInsetAdjustmentBehavior = .never | |||
| webView.allowsBackForwardNavigationGestures = true | |||
| let deviceModel = UIDevice.current.model | |||
| let osVersion = UIDevice.current.systemVersion | |||
| let deviceID = UIDevice.current.identifierForVendor!.uuidString | |||
| let deviceName = UIDevice.current.name | |||
| let FCMToken = Messaging.messaging().fcmToken | |||
| webView.configuration.applicationNameForUserAgent = "Safari/604.1" | |||
| webView.customUserAgent = "Mozilla/5.0 (\(deviceModel); CPU \(deviceModel) OS \(osVersion.replacingOccurrences(of: ".", with: "_")) like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/\(osVersion) Mobile/15E148 Safari/604.1 PWAShell" | |||
| webView.addObserver(NSO, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: NSKeyValueObservingOptions.new, context: nil) | |||
| let localStorageData: [String: Any] = [ | |||
| "model": deviceModel, | |||
| "systemVersion": osVersion, | |||
| "deviceID": deviceID, | |||
| "deviceName": deviceName, | |||
| "FCMtoken" : FCMToken! | |||
| ] | |||
| print("test", localStorageData) | |||
| if JSONSerialization.isValidJSONObject(localStorageData), | |||
| let data = try? JSONSerialization.data(withJSONObject: localStorageData, options: []), | |||
| let value = String(data: data, encoding: .utf8) { | |||
| let _deviceCookie = HTTPCookie(properties: [ | |||
| .domain: rootUrl.host!, | |||
| .path: "/", | |||
| .name: "deviceInfo", | |||
| .value: "\(value)", | |||
| .secure: "FALSE", | |||
| .expires: NSDate(timeIntervalSinceNow: 31556926) | |||
| ])! | |||
| webView.configuration.websiteDataStore.httpCookieStore.setCookie(_deviceCookie) | |||
| } | |||
| #if DEBUG | |||
| if #available(iOS 16.4, *) { | |||
| webView.isInspectable = true | |||
| } | |||
| #endif | |||
| return webView | |||
| } | |||
| func setAppStoreAsReferrer(contentController: WKUserContentController) { | |||
| let scriptSource = "document.referrer = `app-info://platform/ios-store`;" | |||
| let script = WKUserScript(source: scriptSource, injectionTime: .atDocumentEnd, forMainFrameOnly: true) | |||
| contentController.addUserScript(script); | |||
| } | |||
| func setCustomCookie(webView: WKWebView) { | |||
| let _platformCookie = HTTPCookie(properties: [ | |||
| .domain: rootUrl.host!, | |||
| .path: "/", | |||
| .name: platformCookie.name, | |||
| .value: platformCookie.value, | |||
| .secure: "FALSE", | |||
| .expires: NSDate(timeIntervalSinceNow: 31556926) | |||
| ])! | |||
| webView.configuration.websiteDataStore.httpCookieStore.setCookie(_platformCookie) | |||
| } | |||
| func calcWebviewFrame(webviewView: UIView, toolbarView: UIToolbar?) -> CGRect{ | |||
| if ((toolbarView) != nil) { | |||
| return CGRect(x: 0, y: toolbarView!.frame.height, width: webviewView.frame.width, height: webviewView.frame.height - toolbarView!.frame.height) | |||
| } | |||
| else { | |||
| let winScene = UIApplication.shared.connectedScenes.first | |||
| let windowScene = winScene as! UIWindowScene | |||
| var statusBarHeight = windowScene.statusBarManager?.statusBarFrame.height ?? 0 | |||
| switch displayMode { | |||
| case "fullscreen": | |||
| #if targetEnvironment(macCatalyst) | |||
| if let titlebar = windowScene.titlebar { | |||
| titlebar.titleVisibility = .hidden | |||
| titlebar.toolbar = nil | |||
| } | |||
| #endif | |||
| return CGRect(x: 0, y: 0, width: webviewView.frame.width, height: webviewView.frame.height) | |||
| default: | |||
| #if targetEnvironment(macCatalyst) | |||
| statusBarHeight = 29 | |||
| #endif | |||
| let windowHeight = webviewView.frame.height - statusBarHeight | |||
| return CGRect(x: 0, y: statusBarHeight, width: webviewView.frame.width, height: windowHeight) | |||
| } | |||
| } | |||
| } | |||
| extension ViewController: WKUIDelegate, WKDownloadDelegate { | |||
| // redirect new tabs to main webview | |||
| func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? { | |||
| if (navigationAction.targetFrame == nil) { | |||
| webView.load(navigationAction.request) | |||
| } | |||
| return nil | |||
| } | |||
| // restrict navigation to target host, open external links in 3rd party apps | |||
| func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { | |||
| if (navigationAction.request.url?.scheme == "about") { | |||
| return decisionHandler(.allow) | |||
| } | |||
| if (navigationAction.shouldPerformDownload || navigationAction.request.url?.scheme == "blob") { | |||
| return decisionHandler(.download) | |||
| } | |||
| if let requestUrl = navigationAction.request.url{ | |||
| if let requestHost = requestUrl.host { | |||
| // NOTE: Match auth origin first, because host origin may be a subset of auth origin and may therefore always match | |||
| let matchingAuthOrigin = authOrigins.first(where: { requestHost.range(of: $0) != nil }) | |||
| if (matchingAuthOrigin != nil) { | |||
| decisionHandler(.allow) | |||
| if (toolbarView.isHidden) { | |||
| toolbarView.isHidden = false | |||
| webView.frame = calcWebviewFrame(webviewView: webviewView, toolbarView: toolbarView) | |||
| } | |||
| return | |||
| } | |||
| let matchingHostOrigin = allowedOrigins.first(where: { requestHost.range(of: $0) != nil }) | |||
| if (matchingHostOrigin != nil) { | |||
| // Open in main webview | |||
| decisionHandler(.allow) | |||
| if (!toolbarView.isHidden) { | |||
| toolbarView.isHidden = true | |||
| webView.frame = calcWebviewFrame(webviewView: webviewView, toolbarView: nil) | |||
| } | |||
| return | |||
| } | |||
| if (navigationAction.navigationType == .other && | |||
| navigationAction.value(forKey: "syntheticClickType") as! Int == 0 && | |||
| (navigationAction.targetFrame != nil) && | |||
| // no error here, fake warning | |||
| (navigationAction.sourceFrame != nil) | |||
| ) { | |||
| decisionHandler(.allow) | |||
| return | |||
| } | |||
| else { | |||
| decisionHandler(.cancel) | |||
| } | |||
| if ["http", "https"].contains(requestUrl.scheme?.lowercased() ?? "") { | |||
| // Can open with SFSafariViewController | |||
| let safariViewController = SFSafariViewController(url: requestUrl) | |||
| self.present(safariViewController, animated: true, completion: nil) | |||
| } else { | |||
| // Scheme is not supported or no scheme is given, use openURL | |||
| if (UIApplication.shared.canOpenURL(requestUrl)) { | |||
| UIApplication.shared.open(requestUrl) | |||
| } | |||
| } | |||
| } else { | |||
| decisionHandler(.cancel) | |||
| if (navigationAction.request.url?.scheme == "tel" || navigationAction.request.url?.scheme == "mailto" ){ | |||
| if (UIApplication.shared.canOpenURL(requestUrl)) { | |||
| UIApplication.shared.open(requestUrl) | |||
| } | |||
| } | |||
| else { | |||
| if requestUrl.isFileURL { | |||
| // not tested | |||
| downloadAndOpenFile(url: requestUrl.absoluteURL) | |||
| } | |||
| // if (requestUrl.absoluteString.contains("base64")){ | |||
| // downloadAndOpenBase64File(base64String: requestUrl.absoluteString) | |||
| // } | |||
| } | |||
| } | |||
| } | |||
| else { | |||
| decisionHandler(.cancel) | |||
| } | |||
| } | |||
| // Handle javascript: `window.alert(message: String)` | |||
| func webView(_ webView: WKWebView, | |||
| runJavaScriptAlertPanelWithMessage message: String, | |||
| initiatedByFrame frame: WKFrameInfo, | |||
| completionHandler: @escaping () -> Void) { | |||
| // Set the message as the UIAlertController message | |||
| let alert = UIAlertController( | |||
| title: nil, | |||
| message: message, | |||
| preferredStyle: .alert | |||
| ) | |||
| // Add a confirmation action “OK” | |||
| let okAction = UIAlertAction( | |||
| title: "OK", | |||
| style: .default, | |||
| handler: { _ in | |||
| // Call completionHandler | |||
| completionHandler() | |||
| } | |||
| ) | |||
| alert.addAction(okAction) | |||
| // Display the NSAlert | |||
| present(alert, animated: true, completion: nil) | |||
| } | |||
| // Handle javascript: `window.confirm(message: String)` | |||
| func webView(_ webView: WKWebView, | |||
| runJavaScriptConfirmPanelWithMessage message: String, | |||
| initiatedByFrame frame: WKFrameInfo, | |||
| completionHandler: @escaping (Bool) -> Void) { | |||
| // Set the message as the UIAlertController message | |||
| let alert = UIAlertController( | |||
| title: nil, | |||
| message: message, | |||
| preferredStyle: .alert | |||
| ) | |||
| // Add a confirmation action “Cancel” | |||
| let cancelAction = UIAlertAction( | |||
| title: "Cancel", | |||
| style: .cancel, | |||
| handler: { _ in | |||
| // Call completionHandler | |||
| completionHandler(false) | |||
| } | |||
| ) | |||
| // Add a confirmation action “OK” | |||
| let okAction = UIAlertAction( | |||
| title: "OK", | |||
| style: .default, | |||
| handler: { _ in | |||
| // Call completionHandler | |||
| completionHandler(true) | |||
| } | |||
| ) | |||
| alert.addAction(cancelAction) | |||
| alert.addAction(okAction) | |||
| // Display the NSAlert | |||
| present(alert, animated: true, completion: nil) | |||
| } | |||
| // Handle javascript: `window.prompt(prompt: String, defaultText: String?)` | |||
| func webView(_ webView: WKWebView, | |||
| runJavaScriptTextInputPanelWithPrompt prompt: String, | |||
| defaultText: String?, | |||
| initiatedByFrame frame: WKFrameInfo, | |||
| completionHandler: @escaping (String?) -> Void) { | |||
| // Set the message as the UIAlertController message | |||
| let alert = UIAlertController( | |||
| title: nil, | |||
| message: prompt, | |||
| preferredStyle: .alert | |||
| ) | |||
| // Add a confirmation action “Cancel” | |||
| let cancelAction = UIAlertAction( | |||
| title: "Cancel", | |||
| style: .cancel, | |||
| handler: { _ in | |||
| // Call completionHandler | |||
| completionHandler(nil) | |||
| } | |||
| ) | |||
| // Add a confirmation action “OK” | |||
| let okAction = UIAlertAction( | |||
| title: "OK", | |||
| style: .default, | |||
| handler: { _ in | |||
| // Call completionHandler with Alert input | |||
| if let input = alert.textFields?.first?.text { | |||
| completionHandler(input) | |||
| } | |||
| } | |||
| ) | |||
| alert.addTextField { textField in | |||
| textField.placeholder = defaultText | |||
| } | |||
| alert.addAction(cancelAction) | |||
| alert.addAction(okAction) | |||
| // Display the NSAlert | |||
| present(alert, animated: true, completion: nil) | |||
| } | |||
| func downloadAndOpenFile(url: URL){ | |||
| let destinationFileUrl = url | |||
| let sessionConfig = URLSessionConfiguration.default | |||
| let session = URLSession(configuration: sessionConfig) | |||
| let request = URLRequest(url:url) | |||
| let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in | |||
| if let tempLocalUrl = tempLocalUrl, error == nil { | |||
| if let statusCode = (response as? HTTPURLResponse)?.statusCode { | |||
| print("Successfully download. Status code: \(statusCode)") | |||
| } | |||
| do { | |||
| try FileManager.default.copyItem(at: tempLocalUrl, to: destinationFileUrl) | |||
| self.openFile(url: destinationFileUrl) | |||
| } catch (let writeError) { | |||
| print("Error creating a file \(destinationFileUrl) : \(writeError)") | |||
| } | |||
| } else { | |||
| print("Error took place while downloading a file. Error description: \(error?.localizedDescription ?? "N/A") ") | |||
| } | |||
| } | |||
| task.resume() | |||
| } | |||
| // func downloadAndOpenBase64File(base64String: String) { | |||
| // // Split the base64 string to extract the data and the file extension | |||
| // let components = base64String.components(separatedBy: ";base64,") | |||
| // // Make sure the base64 string has the correct format | |||
| // guard components.count == 2, let format = components.first?.split(separator: "/").last else { | |||
| // print("Invalid base64 string format") | |||
| // return | |||
| // } | |||
| // // Remove the data type prefix to get the base64 data | |||
| // let dataString = components.last! | |||
| // if let imageData = Data(base64Encoded: dataString) { | |||
| // let documentsUrl: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! | |||
| // let destinationFileUrl = documentsUrl.appendingPathComponent("image.\(format)") | |||
| // do { | |||
| // try imageData.write(to: destinationFileUrl) | |||
| // self.openFile(url: destinationFileUrl) | |||
| // } catch { | |||
| // print("Error writing image to file url: \(destinationFileUrl): \(error)") | |||
| // } | |||
| // } | |||
| // } | |||
| func openFile(url: URL) { | |||
| self.documentController = UIDocumentInteractionController(url: url) | |||
| self.documentController?.delegate = self | |||
| self.documentController?.presentPreview(animated: true) | |||
| } | |||
| func webView(_ webView: WKWebView, navigationAction: WKNavigationAction, didBecome download: WKDownload) { | |||
| download.delegate = self | |||
| } | |||
| func download(_ download: WKDownload, decideDestinationUsing response: URLResponse, | |||
| suggestedFilename: String, | |||
| completionHandler: @escaping (URL?) -> Void) { | |||
| let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] | |||
| let fileURL = documentsPath.appendingPathComponent(suggestedFilename) | |||
| self.openFile(url: fileURL) | |||
| completionHandler(fileURL) | |||
| } | |||
| } | |||
| @ -0,0 +1,21 @@ | |||
| # Uncomment the next line to define a global platform for your project | |||
| platform :ios, '15.0' | |||
| target 'Nivesh' do | |||
| # Comment the next line if you don't want to use dynamic frameworks | |||
| use_frameworks! | |||
| # Add the pod for Firebase Cloud Messaging | |||
| pod 'FirebaseCore' | |||
| pod 'FirebaseAnalytics' | |||
| pod 'Firebase/Messaging' | |||
| end | |||
| post_install do |installer| | |||
| installer.pods_project.targets.each do |target| | |||
| target.build_configurations.each do |config| | |||
| config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0' | |||
| end | |||
| end | |||
| end | |||
Powered by TurnKey Linux.