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