jsoncreator_app/JSONCreator_iOS/JSONCreator/AppDelegate.swift
Matt Bruce d7781c5532 updated
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
2022-03-16 09:12:42 -05:00

558 lines
23 KiB
Swift

//
// AppDelegate.swift
// JSONCreator
//
// Created by Scott Pfeil on 8/2/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import UIKit
import CoreTelephony
extension Decodable {
static func map(JSONString:String) -> Self? {
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
return try decoder.decode(Self.self, from: Data(JSONString.utf8))
} catch let error {
print(error)
return nil
}
}
}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate {
var window: UIWindow?
var mvcNav: UINavigationController?
var dvcNav: UINavigationController?
var mvc: UIViewController?
var dvc: UIViewController?
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
// Setup our core object with the default implementation
CoreUIObject.sharedInstance()?.defaultInitialSetup()
CoreUIObject.sharedInstance()?.globalTopAlertDelegate = self
return true
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let splitViewController = window!.rootViewController as! UISplitViewController
mvcNav = splitViewController.viewControllers[0] as? UINavigationController
mvcNav?.delegate = self
mvc = mvcNav?.topViewController
dvcNav = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as? UINavigationController
dvc = dvcNav?.topViewController
dvc?.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem
dvc?.navigationItem.leftItemsSupplementBackButton = true
splitViewController.delegate = self
splitViewController.preferredDisplayMode = .allVisible
let gr = UILongPressGestureRecognizer(target: self, action: #selector(jsonPasteAndGo))
splitViewController.view.addGestureRecognizer(gr)
NotificationCenter.default.addObserver(forName: UIViewController.showDetailTargetDidChangeNotification, object: splitViewController, queue: nil) { [weak self] (notification) in
if let strongSelf = self, let svc = notification.object as? UISplitViewController {
if svc.isCollapsed {
strongSelf.mvc?.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Editor", style: .plain, target: self, action: #selector(self?.showEditor))
} else {
strongSelf.mvcNav?.setViewControllers([strongSelf.mvc!], animated: false)
strongSelf.mvc?.navigationItem.rightBarButtonItem = nil
}
}
}
self.register()
//getCT()
let json = ["actionType" : WebViewBridgeTrialFraudUserGetModel.identifier]
self.testBridge(json: json)
return true
}
// func getCT() {
// let info: CTTelephonyNetworkInfo = CTTelephonyNetworkInfo()
// if #available(iOS 12.0, *) {
// for (service, carrier) in info.serviceSubscriberCellularProviders ?? [:] {
// print("\(service), \(carrier)")
// print(carrier.carrierName!)
// print(carrier.mobileCountryCode!)
// print(carrier.mobileNetworkCode!)
// print(carrier.isoCountryCode!)
// print(carrier.allowsVOIP)
// }
// } else {
// // Fallback on earlier versions
// }
// }
@objc func jsonPasteAndGo(_ sender: UILongPressGestureRecognizer) {
if sender.state == .ended {
(dvc as? DetailViewController)?.textView.text = UIPasteboard.general.string
(dvc as? DetailViewController)?.play()
}
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
// MARK: - Split view
func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool {
//guard let secondaryAsNavController = secondaryViewController as? UINavigationController else { return false }
//guard let _ = secondaryAsNavController.topViewController as? DetailViewController else { return false }
return true
}
@objc func showEditor() {
mvcNav?.pushViewController(dvc!, animated: true)
}
}
extension AppDelegate: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
if mvc == viewController {
dvcNav?.setViewControllers([dvc!], animated: false)
}
}
}
extension AppDelegate: MVMCoreGlobalTopAlertDelegateProtocol {
func getTopAlertView() -> UIView & MVMCoreTopAlertViewProtocol {
guard let topAlertView = MVMCoreUISplitViewController.main()?.topAlertView else {
return MVMCoreUITopAlertView()
}
return topAlertView;
}
func priorityForTopAlert(by object: MVMCoreTopAlertObject) -> Operation.QueuePriority {
return object.queuePriority
}
}
extension Result{
public func get() throws -> Success {
switch self {
case .success(let value):
return value
case .failure(let error):
throw error
}
}
}
extension AppDelegate {
func register(){
ModelRegistry.register(handler: WebViewBridgeTrialFraudDeviceCheckGet.self, for: WebViewBridgeTrialFraudDeviceCheckGetModel.self)
//ModelRegistry.register(handler: WebViewBridgeTrialFraudUserSet.self, for: WebViewBridgeTrialFraudUserSetModel.self)
ModelRegistry.register(handler: WebViewBridgeTrialFraudUserGet.self, for: WebViewBridgeTrialFraudUserGetModel.self)
ModelRegistry.register(handler: EmailVerifyField.self, for: EmailVerifyModel.self)
ModelRegistry.register(handler: PillLabel.self, for: PillLabelModel.self)
ModelRegistry.register(handler: SampleWebViewBridge.self, for: SampleWebViewBridgeModel.self)
}
func testBridge(json: [String: Any]){
do {
let bridgeModel = try ModelRegistry.getBridgeModelForJSON(json)
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "Webview bridge JSON: \(String(describing: bridgeModel.toJSONString()))")
let bridgeType = try ModelRegistry.getHandler(bridgeModel) as! WebViewBridgeProtocol.Type
let bridge = try bridgeType.init(baseModel: bridgeModel,
requestId: UUID().uuidString,
viewController: nil)
let anyHandler = bridge.eraseToAnyHandler()
MVMCoreDispatchUtility.performBlock(inBackground: {
print("Thread isMain: \(Thread.isMainThread)")
anyHandler.perform(then: { result in
print("Thread isMain: \(Thread.isMainThread)")
switch result{
case .success(let value):
if let value = value {
print(value)
} else {
print("empty dictionary")
}
case .failure(_):
print("error")
}
})
})
} catch {
print(error.localizedDescription)
}
}
func testJSONValue(){
// let json = """
// {
// "name" : "Matt",
// "params": {
// "stringKey": "Blah",
// "doubleKey": 1.02,
// "intKey": 105,
// "boolKey": true,
// "arrayKey": ["val1","val2", "val3"],
// "objectKey": { "foo": "fooName" }
// }
// }
// """
//
// struct Test: Decodable {
// var name: String
// var params: JSONValueDictionary
// }
//
//
// if let test = Test.map(JSONString: json) {
//
// func debug(key: String, value: Any?){
// print("\(key): \(value!) type:\(type(of: value!))")
// }
// do {
// let stringKey: String = try test.params["stringKey"]!.value()
// let doubleKey: Double = try test.params["doubleKey"]!.value()
// let intKey: Int = try test.params["intKey"]!.value()
// let boolKey: Bool = try test.params["boolKey"]!.value()
// let arrayKey: [String] = try test.params["arrayKey"]!.value()
// let objectKey: [String: Any] = try test.params["objectKey"]!.value()
//
// print("Using Value")
// debug(key: "stringKey", value: stringKey)
// debug(key: "doubleKey", value: doubleKey)
// debug(key: "intKey", value: intKey)
// debug(key: "boolKey", value: boolKey)
// debug(key: "arrayKey", value: arrayKey)
// debug(key: "objectKey", value: objectKey)
// print("")
//
// print("Using baseValue")
// let bstringKey = test.params["stringKey"]?.base as? String
// let bdoubleKey = test.params["doubleKey"]?.base as? Double
// let bintKey = test.params["intKey"]?.base as? Int
// let bboolKey = test.params["boolKey"]?.base as? Bool
// let barrayKey = test.params["arrayKey"]?.base as? [String]
// let bobjectKey = test.params["objectKey"]?.base as? [String: Any]
// debug(key: "stringKey", value: bstringKey)
// debug(key: "doubleKey", value: bdoubleKey)
// debug(key: "intKey", value: bintKey)
// debug(key: "boolKey", value: bboolKey)
// debug(key: "arrayKey", value: barrayKey)
// debug(key: "objectKey", value: bobjectKey)
// print("")
//
// print("Using toMethod")
// let cstringKey = try test.params["stringKey"]?.toString()
// let cdoubleKey = try test.params["doubleKey"]?.toDouble()
// let cintKey = try test.params["intKey"]?.toInt()
// let cboolKey = try test.params["boolKey"]?.toBool()
// let carrayKey = try test.params["arrayKey"]?.toArray(of: String.self)
// let cobjectKey = try test.params["objectKey"]?.toObject(of: [String: Any].self)
// debug(key: "stringKey", value: cstringKey)
// debug(key: "doubleKey", value: cdoubleKey)
// debug(key: "intKey", value: cintKey)
// debug(key: "boolKey", value: cboolKey)
// debug(key: "arrayKey", value: carrayKey)
// debug(key: "objectKey", value: cobjectKey)
// print("")
// } catch {
// print(error)
// }
// }
}
}
final public class SampleWebViewBridgeModel: MoleculeModelProtocol{
public var backgroundColor: Color?
public static var identifier: String = "sampleWebViewBridge"
public var moleculeName: String = SampleWebViewBridgeModel.identifier
}
import WebKit
final public class SampleWebViewBridge: WebView{
func getNonBridgeActions() -> [String: [String: Any]] {
let openPage: [String: Any] = [
"actionType": "openPage",
"pageType": "feedsAuthenticatedWebview",
"extraParameters": [
"browserUrl" : "www.verizon.com"
]
]
let passMVAData: [String: Any] = [
"actionType": "passMVAData",
"data": [
"backIgnoresWebHistory": true
]
]
let hideBackButton: [String: Any] = [
"actionType": "updateNavigation",
"navigationBar":[
"moleculeName": "navigationBar",
"alwaysShowBackButton": false,
"title":"Page title"
]
]
return [
"openPage": openPage,
"passMVAData": passMVAData,
"hideBackButton": hideBackButton
]
}
}
@objcMembers open class EmailVerifyModel: MoleculeModelProtocol {
public static var identifier: String = "emailVerifyField"
public var moleculeName: String = EmailVerifyModel.identifier
public var emailField: TextEntryFieldModel
public var bottomMolecule: MoleculeModelProtocol
public var email: String
public var backgroundColor: Color?
public init(emailField: TextEntryFieldModel, email: String, bottomMolecule: MoleculeModelProtocol) {
self.emailField = emailField
self.email = email
self.bottomMolecule = bottomMolecule
}
public required init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
emailField = try typeContainer.decode(TextEntryFieldModel.self, forKey: .emailField)
email = try typeContainer.decode(String.self, forKey: .email)
bottomMolecule = try typeContainer.decodeModel(codingKey: .bottomMolecule)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(emailField, forKey: .emailField)
try container.encode(email, forKey: .email)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeModel(bottomMolecule, forKey: .bottomMolecule)
}
private enum CodingKeys: String, CodingKey {
case moleculeName
case emailField
case bottomMolecule
case backgroundColor
case email
}
}
@objcMembers open class EmailVerifyField: View {
private let emailField = TextEntryField()
private var bottomView: MoleculeViewProtocol?
private var emailVerifyFieldModel: EmailVerifyModel? {
return model as? EmailVerifyModel
}
private var isBottomViewHidden: Bool {
guard let emailVerifyFieldModel = emailVerifyFieldModel, let text = emailField.text else { return true }
return !(emailVerifyFieldModel.email.caseInsensitiveCompare(text) == .orderedSame)
}
private let containerView = MVMCoreUICommonViewsUtility.commonView()
open override func setupView() {
super.setupView()
backgroundColor = .clear
clipsToBounds = true
addSubview(containerView)
NSLayoutConstraint.constraintPinSubview(toSuperview: containerView)
containerView.addSubview(emailField)
NSLayoutConstraint.constraintPinSubview(emailField, pinTop: true, pinBottom: false, pinLeft: true, pinRight: true)
addEmailFieldObserver()
}
private func addEmailFieldObserver() {
NotificationCenter.default.addObserver(self, selector: #selector(onEmailValueChange), name: UITextField.textDidChangeNotification, object: emailField.textField)
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? EmailVerifyModel else { return }
emailField.set(with: model.emailField, delegateObject, additionalData)
if let bottomView = self.bottomView ?? ModelRegistry.createMolecule(model.bottomMolecule, delegateObject: delegateObject, additionalData: additionalData) {
bottomView.set(with: model.bottomMolecule, delegateObject, additionalData)
self.bottomView = bottomView
addBottomView(bottomView: bottomView)
}
}
public func onEmailValueChange() {
bottomView?.isHidden = isBottomViewHidden
}
private func addBottomView(bottomView: MoleculeViewProtocol) {
containerView.addSubview(bottomView)
bottomView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true
containerView.trailingAnchor.constraint(equalTo: bottomView.trailingAnchor).isActive = true
bottomView.topAnchor.constraint(equalTo: emailField.bottomAnchor).isActive = true
containerView.bottomAnchor.constraint(equalTo: bottomView.bottomAnchor).isActive = true
bottomView.isHidden = isBottomViewHidden
}
}
@objcMembers public class PillLabelModel: MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "pillLabel"
public var backgroundColor: Color? = Color(uiColor: .mvmRed)
public var text: String
public var accessibilityText: String?
public var textColor: Color = Color(uiColor: .mvmWhite)
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case text
case accessibilityText
case textColor
}
//--------------------------------------------------
// MARK: - codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
if let backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) {
self.backgroundColor = backgroundColor
}
text = try typeContainer.decode(String.self, forKey: .text)
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
if let textColor = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor) {
self.textColor = textColor
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encode(text, forKey: .text)
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
try container.encode(textColor, forKey: .textColor)
}
}
@objcMembers open class PillLabel: View {
//--------------------------------------------------
// MARK: - Outlets
//--------------------------------------------------
public let label = Label(fontStyle: .BoldMicro)
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
override open func setupView() {
super.setupView()
label.textAlignment = .center
label.textColor = .mvmWhite
backgroundColor = .mvmRed
addSubview(label)
NSLayoutConstraint.activate([
label.topAnchor.constraint(equalTo: topAnchor, constant: 2),
label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: Padding.Three),
trailingAnchor.constraint(equalTo: label.trailingAnchor, constant: Padding.Three),
bottomAnchor.constraint(equalTo: label.bottomAnchor, constant: 2)
])
}
@objc override open func updateView(_ size: CGFloat) {
super.updateView(size)
label.updateView(size)
}
open override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = bounds.height / 2
}
open override func reset() {
super.reset()
label.text = ""
label.accessibilityLabel = ""
label.textColor = .white
backgroundColor = .mvmRed
}
//--------------------------------------------------
// MARK: - Atomic
//--------------------------------------------------
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let model = model as? PillLabelModel else { return }
label.text = model.text
if let accessibilityText = model.accessibilityText {
label.accessibilityLabel = accessibilityText
}
label.textColor = model.textColor.uiColor
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 20
}
}
extension PillLabel: MVMCoreUIViewConstrainingProtocol {
public func horizontalAlignment() -> UIStackView.Alignment {
return .leading
}
}