| @ -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.