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