1923 lines
80 KiB
Swift
1923 lines
80 KiB
Swift
//
|
|
// ViewController.swift
|
|
// Befund
|
|
//
|
|
// Created by Irakli Abetschkhrischwili on 29.04.22.
|
|
// Copyright © 2022 MVZ Dr. Stein und Kollegen. All rights reserved.
|
|
|
|
import AVFoundation
|
|
import UIKit
|
|
|
|
class ViewController: UIViewController, UIAlertViewDelegate, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate, UNUserNotificationCenterDelegate, UpdatingParentCheckBox
|
|
{
|
|
//MARK: *** ViewController
|
|
public static var CurrentViewController: ViewController? = nil
|
|
public static var Settings: Core.Models.Settings? = nil
|
|
public static var currentlySelectedBarcode: String = ""
|
|
|
|
@IBOutlet weak var DashedArea: UIView!
|
|
@IBOutlet weak var LBLNORESULTS: UILabel!
|
|
//@IBOutlet weak var LBL_NEW_RESULTS: UILabel!
|
|
@IBOutlet weak var LBL_MY_RESULTS: UILabel!
|
|
@IBOutlet weak var LBL_HINWEIS: UILabel!
|
|
@IBOutlet weak var ResultsTable: UITableView!
|
|
private var ResultsTableRefresher: UIRefreshControl!
|
|
@IBOutlet weak var MainLoading: UIActivityIndicatorView!
|
|
|
|
private var dbResults: Array<Core.Models.Database.Results>? = nil
|
|
|
|
//MARK: *** PopupNewPGS
|
|
|
|
@IBOutlet weak var PopupNewPGS_Overlay: UIView!
|
|
@IBOutlet weak var PopupNewPGS: UIView!
|
|
|
|
//MARK: *** PopupNewPGS - PGS
|
|
@IBOutlet weak var PopupNewPGS_PGS: UIView!
|
|
@IBOutlet weak var PopupNewPGS_ZipView: UIView!
|
|
@IBOutlet weak var PopupNewPGS_BirthdayView: UIView!
|
|
@IBOutlet weak var PopupNewPGS_SampleidView: UIView!
|
|
@IBOutlet weak var PopupNewPGS_txtZIP: UITextField!
|
|
@IBOutlet weak var PopupNewPGS_txtBirthday: UITextField!
|
|
let PopupNewPGS_dtBirthday = UIDatePicker()
|
|
@IBOutlet weak var PopupNewPGS_txtSampleid: UITextField!
|
|
@IBOutlet weak var PopupNwePGS_btnScanBarcode: UIButton!
|
|
@IBOutlet weak var PopupNewPGS_Loading: UIActivityIndicatorView!
|
|
@IBOutlet weak var PopupNewPGS_Status: UILabel!
|
|
@IBOutlet weak var PopupNewPGS_labPwdHinweis: UILabel!
|
|
|
|
//MARK: *** PopupNewPGS - MasterPassword
|
|
@IBOutlet weak var PopupNewPGS_MasterPassword: UIView!
|
|
@IBOutlet weak var PopupNewPGS_PasswordConfirmView: UIView!
|
|
@IBOutlet weak var PopupNewPGS_PasswordView: UIView!
|
|
|
|
@IBOutlet weak var PopupNewPGS_txtPassword: UITextField!
|
|
@IBOutlet weak var PopupNewPGS_txtPasswordConfirm: UITextField!
|
|
@IBOutlet weak var PopupNewPGS_txtPin: UITextField!
|
|
@IBOutlet weak var PopupNewPGS_PrivatePolicyArea: UIView!
|
|
@IBOutlet weak var PopupNewPGS_BtnPrivatePolicy: UIButton!
|
|
|
|
//MARK: *** PopupNewPGS - Buttons
|
|
@IBOutlet weak var PopupNewPGS_BtnAdd: UIButton!
|
|
@IBOutlet weak var PopupNewPGS_BtnCancel: UIButton!
|
|
|
|
//MARK: *** PopupPasswordConfirm
|
|
@IBOutlet weak var PopupPasswordConfirm_Overlay: UIView!
|
|
@IBOutlet weak var PopupPasswordConfirm: UIView!
|
|
@IBOutlet weak var PopupPasswordConfirm_BtnCancel: UIButton!
|
|
@IBOutlet weak var PopupPasswordConfirm_BtnEncrypt: UIButton!
|
|
@IBOutlet weak var PopupPasswordConfirm_PasswordView: UIView!
|
|
@IBOutlet weak var PopupPasswordConfirm_txtPassword: UITextField!
|
|
@IBOutlet weak var PopupPasswordConfirm_Loading: UIActivityIndicatorView!
|
|
@IBOutlet weak var PopupPasswordConfirm_Status: UILabel!
|
|
|
|
|
|
//MARK: *** PopupPrivatePolicy
|
|
@IBOutlet weak var PopupPrivatePolicy_Overlay: UIView!
|
|
@IBOutlet weak var PopupPrivatePolicy: UIView!
|
|
|
|
@IBOutlet weak var PopupPrivatePolicy_TextLabel: UILabel!
|
|
@IBOutlet weak var PopupPrivatePolicy_BtnAccept: UIButton!
|
|
@IBOutlet weak var PopupPrivatePolicy_HeadLabel: UILabel!
|
|
|
|
|
|
// PopupPushNotification
|
|
@IBOutlet weak var PopupPush_Overlay: UIView!
|
|
@IBOutlet weak var PopupPush_Content: UIView!
|
|
|
|
@IBOutlet weak var PopupPush_LabelText: UILabel!
|
|
@IBOutlet weak var PopupPush_LabelHeader: UILabel!
|
|
@IBOutlet weak var PopupPush_BtnYes: UIButton!
|
|
@IBOutlet weak var PopupPush_BtnNo: UIButton!
|
|
|
|
|
|
//MARK: *** Processing objects
|
|
private var CurrentDownload: Core.Models.Response.Download? = nil
|
|
private var CurrentDownloadResults: Core.Models.Database.Results? = nil
|
|
private var CurrentDownloadProcessing: Bool = false
|
|
private var LoadingData: Bool = false
|
|
|
|
//MARK: Bottom Menu
|
|
@IBOutlet weak var BottomMenu: UIView!
|
|
|
|
@IBOutlet weak var launch_Overlay: UIView!
|
|
@IBOutlet weak var launch_LimbachLogo: UIImageView!
|
|
@IBOutlet weak var launch_LaborLogo: UIImageView!
|
|
|
|
//private let privatePolicyLink = "https://www.limbachgruppe.com/fileadmin/downloads/6406135946.html"
|
|
|
|
|
|
private var afterInitialize: Bool = false
|
|
|
|
@IBOutlet var PopupPrivatePolicy_Checkbox: CheckBoxButton!
|
|
public var confirmCheckBox: CheckBoxButton! {
|
|
get {
|
|
return PopupPrivatePolicy_Checkbox
|
|
}
|
|
}
|
|
|
|
override func viewDidLoad()
|
|
{
|
|
super.viewDidLoad()
|
|
self.Initialize()
|
|
NotificationCenter.default.addObserver(self, selector: #selector(appActivated), name: UIApplication.didBecomeActiveNotification, object: nil)
|
|
}
|
|
|
|
@objc func appActivated()
|
|
{
|
|
if (self.viewIfLoaded?.window != nil && !self.CurrentDownloadProcessing)
|
|
{
|
|
self.dashedAreaLongPressed(sender: UILongPressGestureRecognizer())
|
|
}
|
|
}
|
|
|
|
override func viewDidAppear(_ animated: Bool) {
|
|
super.viewDidAppear(animated)
|
|
|
|
self.SetLabels()
|
|
ViewController.Settings = Core.Models.Settings.loadFromFile(atPath: Core.System.SettingsPath())
|
|
|
|
if (!self.PopupNewPGS_Overlay.isHidden && ViewController.currentlySelectedBarcode.count > 0)
|
|
{
|
|
self.PopupNewPGS_txtSampleid.text = ViewController.currentlySelectedBarcode
|
|
ViewController.currentlySelectedBarcode = ""
|
|
}
|
|
|
|
if (self.afterInitialize){
|
|
self.afterInitialize = false
|
|
self.ShowLaborLogo()
|
|
}
|
|
else
|
|
{
|
|
self.ShowMainView()
|
|
}
|
|
}
|
|
|
|
private func ShowMainView()
|
|
{
|
|
if(AppDelegate.Session.DevicePassword == nil && (ViewController.Settings?.verificator_hash != nil))
|
|
{
|
|
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
|
let devicePwdController = storyboard.instantiateViewController(identifier: "LoginController")
|
|
|
|
devicePwdController.modalPresentationStyle = .fullScreen
|
|
let transition = CATransition()
|
|
transition.duration = 0.25
|
|
transition.type = .push
|
|
transition.subtype = .fromRight
|
|
self.view.window!.layer.add(transition, forKey: kCATransition)
|
|
self.present(devicePwdController, animated: false)
|
|
}
|
|
else
|
|
{
|
|
if(ViewController.Settings?.udid != nil)
|
|
{
|
|
self.loadResults()
|
|
}
|
|
}
|
|
|
|
if(!(ViewController.Settings?.pushNotificationExplained ?? false))
|
|
{
|
|
self.ShowPopup(overlay: self.PopupPush_Overlay, content: self.PopupPush_Content)
|
|
}
|
|
else
|
|
{
|
|
self.AskForPushPermissions()
|
|
}
|
|
|
|
}
|
|
|
|
private func ShowLaborLogo()
|
|
{
|
|
if ((ViewController.Settings?.labor?.id ?? "").count > 0 )
|
|
{
|
|
self.launch_Overlay.isHidden = false
|
|
|
|
self.launch_LaborLogo.image = ViewController.Settings!.labor!.logo
|
|
self.launch_LaborLogo.frame.origin = CGPoint(x: -self.view.frame.width, y: self.launch_LimbachLogo.frame.origin.y)
|
|
self.launch_LaborLogo.isHidden = false
|
|
|
|
let storeX = self.launch_LimbachLogo.frame.origin.x
|
|
|
|
UIView.animate(withDuration: 1.00, animations: {
|
|
self.launch_LimbachLogo.frame.origin = CGPoint(x: self.view.frame.width, y: self.launch_LimbachLogo.frame.origin.y)
|
|
self.launch_LaborLogo.frame.origin = CGPoint(x: storeX, y: self.launch_LaborLogo.frame.origin.y)
|
|
}) {_ in
|
|
sleep(1)
|
|
self.launch_Overlay.isHidden = true
|
|
self.ShowMainView()
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
self.ShowMainView()
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Initializes view
|
|
*/
|
|
private func Initialize()
|
|
{
|
|
self.afterInitialize = true
|
|
//MARK: *** ViewController
|
|
|
|
ViewController.CurrentViewController = self
|
|
ViewController.Settings = Core.Models.Settings.loadFromFile(atPath: Core.System.SettingsPath())
|
|
|
|
self.PopupNewPGS_MasterPassword.isHidden = true
|
|
self.PopupNewPGS_HideLoading()
|
|
|
|
self.launch_Overlay.frame = self.view.frame
|
|
self.view.addSubview(self.launch_Overlay)
|
|
|
|
//MARK: *** PopupNewPGS
|
|
self.PopupNewPGS_Overlay.frame = self.view.frame
|
|
self.view.addSubview(self.PopupNewPGS_Overlay)
|
|
|
|
var popupFieldHeight = (self.PopupNewPGS_PGS.frame.size.height / 3)
|
|
|
|
if(popupFieldHeight > 100)
|
|
{
|
|
popupFieldHeight = 100
|
|
}
|
|
|
|
let popupFieldMargin = ((popupFieldHeight * 5) / 100)
|
|
popupFieldHeight = popupFieldHeight - (3 * popupFieldMargin)
|
|
|
|
self.PopupNewPGS_ZipView.frame.size.height = popupFieldHeight
|
|
|
|
self.PopupNewPGS_BirthdayView.frame.size.height = popupFieldHeight
|
|
self.PopupNewPGS_BirthdayView.frame.origin = CGPoint(x: self.PopupNewPGS_BirthdayView.frame.origin.x, y: self.PopupNewPGS_ZipView.frame.origin.y + self.PopupNewPGS_ZipView.frame.size.height + popupFieldMargin)
|
|
|
|
self.PopupNewPGS_SampleidView.frame.size.height = popupFieldHeight
|
|
self.PopupNewPGS_SampleidView.frame.origin = CGPoint(x: self.PopupNewPGS_SampleidView.frame.origin.x, y: self.PopupNewPGS_BirthdayView.frame.origin.y + self.PopupNewPGS_BirthdayView.frame.size.height + popupFieldMargin)
|
|
|
|
self.PopupNewPGS_txtZIP.delegate = self
|
|
self.PopupNewPGS_txtBirthday.delegate = self
|
|
self.PopupNewPGS_txtSampleid.delegate = self
|
|
self.PopupNewPGS_txtPassword.delegate = self
|
|
self.PopupNewPGS_txtPassword.enablePasswordToggle()
|
|
self.PopupNewPGS_txtPasswordConfirm.delegate = self
|
|
self.PopupNewPGS_txtPasswordConfirm.enablePasswordToggle()
|
|
self.PopupNewPGS_txtPin.delegate = self
|
|
|
|
self.PopupNewPGS_txtZIP.returnKeyType = .next
|
|
self.PopupNewPGS_txtBirthday.returnKeyType = .next
|
|
self.PopupNewPGS_txtSampleid.returnKeyType = .done
|
|
self.PopupNewPGS_txtPassword.returnKeyType = .next
|
|
self.PopupNewPGS_txtPasswordConfirm.returnKeyType = .next
|
|
self.PopupNewPGS_txtPin.returnKeyType = .done
|
|
|
|
self.PopupPrivatePolicy_Checkbox = CheckBoxButton(frame: CGRect(x: 10, y: 5, width: 30, height: 30))
|
|
self.PopupNewPGS_PrivatePolicyArea.addSubview(self.PopupPrivatePolicy_Checkbox)
|
|
let gesture = UITapGestureRecognizer(target: self, action: #selector(didTapCheckbox))
|
|
self.PopupPrivatePolicy_Checkbox.addGestureRecognizer(gesture)
|
|
self.PopupPrivatePolicy_Checkbox.setChecked(flag: true)
|
|
|
|
self.addDoneToolbar([self.PopupNewPGS_txtZIP, self.PopupNewPGS_txtSampleid, self.PopupNewPGS_txtPassword, self.PopupNewPGS_txtPasswordConfirm, self.PopupNewPGS_txtPin])
|
|
|
|
self.hideKeyboardWhenTappedAround()
|
|
self.createDatePicker()
|
|
|
|
//MARK: *** Table
|
|
self.DashedArea.addDashedBorder()
|
|
self.ResultsTableRefresher = UIRefreshControl()
|
|
let attributes = [NSAttributedString.Key.foregroundColor: UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.8), NSAttributedString.Key.font: UIFont.systemFont(ofSize: 15.0)]
|
|
self.ResultsTableRefresher.attributedTitle = NSAttributedString(string: Core.Lang.Get(key: "MSG_DATA_REFRESHING"), attributes: attributes)
|
|
self.ResultsTableRefresher.tintColor = .clear
|
|
self.ResultsTableRefresher.addTarget(self, action: #selector(tableRefresh), for: .valueChanged)
|
|
self.ResultsTable.addSubview(self.ResultsTableRefresher)
|
|
self.ResultsTable.isHidden = true
|
|
self.LBLNORESULTS.isHidden = false
|
|
self.ResultsTable.delegate = self
|
|
self.ResultsTable.dataSource = self
|
|
self.ResultsTable.contentInset = .init(top: 0, left: 0, bottom: 70, right: 0)
|
|
self.ResultsTable.register(ResultsTableViewCell.nib(), forCellReuseIdentifier: ResultsTableViewCell.identifier)
|
|
|
|
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(dashedAreaLongPressed))
|
|
self.DashedArea.addGestureRecognizer(longPressRecognizer)
|
|
|
|
//MARK: *** PopupPasswordConfirm
|
|
|
|
self.PopupPasswordConfirm_Overlay.isHidden = true
|
|
self.PopupPasswordConfirm_HideLoading()
|
|
|
|
self.PopupPasswordConfirm_Overlay.frame = self.view.frame
|
|
self.view.addSubview(self.PopupPasswordConfirm_Overlay)
|
|
self.PopupPasswordConfirm_txtPassword.delegate = self
|
|
self.PopupPasswordConfirm_txtPassword.enablePasswordToggle()
|
|
|
|
self.MainLoadingHide()
|
|
|
|
if(ViewController.Settings?.udid != nil)
|
|
{
|
|
self.PopupNewPGS_BtnAdd.setTitle(Core.Lang.Get(key: "BTN_ADD"), for: .normal)
|
|
self.loadResults()
|
|
}
|
|
else
|
|
{
|
|
self.PopupNewPGS_BtnAdd.setTitle(Core.Lang.Get(key: "BTN_NEXT"), for: .normal)
|
|
}
|
|
|
|
self.PopupNwePGS_btnScanBarcode.setTitle("", for: .normal)
|
|
|
|
self.PopupPrivatePolicy_Overlay.frame = self.view.frame
|
|
self.view.addSubview(self.PopupPrivatePolicy_Overlay)
|
|
self.PopupPrivatePolicy_Overlay.isHidden = true
|
|
|
|
|
|
//MARK: Bottom Menu
|
|
self.BottomMenu.transform = CGAffineTransform(rotationAngle: CGFloat(5.0 * .pi / 180))
|
|
self.BottomMenu.frame.origin.y = UIScreen.main.bounds.height
|
|
|
|
|
|
self.PopupPush_Overlay.frame = self.view.frame
|
|
self.view.addSubview(self.PopupPush_Overlay)
|
|
self.PopupPush_Overlay.isHidden = true
|
|
|
|
self.PopupNewPGS_labPwdHinweis.text = ""
|
|
self.PopupNewPGS_labPwdHinweis.isHidden = false
|
|
self.PopupNewPGS_txtPassword.addTarget(self, action: #selector(self.ShowPWDHinweis), for: .editingDidBegin)
|
|
self.PopupNewPGS_txtPassword.addTarget(self, action: #selector(self.HidePWDHinweis), for: .editingDidEnd)
|
|
self.PopupNewPGS_txtPasswordConfirm.addTarget(self, action: #selector(self.ShowPWDHinweis), for: .editingDidBegin)
|
|
self.PopupNewPGS_txtPasswordConfirm.addTarget(self, action: #selector(self.HidePWDHinweis), for: .editingDidEnd)
|
|
self.PopupNewPGS_txtPin.addTarget(self, action: #selector(self.ShowPinHinweis), for: .editingDidBegin)
|
|
self.PopupNewPGS_txtPin.addTarget(self, action: #selector(self.HidePWDHinweis), for: .editingDidEnd)
|
|
|
|
}
|
|
|
|
@objc func ShowPWDHinweis()
|
|
{
|
|
self.PopupNewPGS_Status.text = ""
|
|
|
|
self.PopupNewPGS_labPwdHinweis.text = Core.Lang.Get(key: "ERROR_ENTER_STRONG_PASSWORD")
|
|
self.PopupNewPGS_labPwdHinweis.isHidden = false
|
|
}
|
|
|
|
@objc func ShowPinHinweis()
|
|
{
|
|
self.PopupNewPGS_Status.text = ""
|
|
|
|
self.PopupNewPGS_labPwdHinweis.text = Core.Lang.Get(key: "ERROR_PIN_LENGTH")
|
|
self.PopupNewPGS_labPwdHinweis.isHidden = false
|
|
}
|
|
|
|
|
|
@objc func HidePWDHinweis()
|
|
{
|
|
self.PopupNewPGS_labPwdHinweis.text = ""
|
|
self.PopupNewPGS_labPwdHinweis.isHidden = true
|
|
}
|
|
|
|
private func SetLabels()
|
|
{
|
|
|
|
// Initialize Language
|
|
self.LBL_MY_RESULTS.text = Core.Lang.Get(key: "LBL_MY_RESULTS")
|
|
self.LBL_HINWEIS.text = Core.Lang.Get(key: "LBL_BEFUND_HINWEIS")
|
|
self.PopupNewPGS_txtZIP.placeholder = Core.Lang.Get(key: "LBL_ZIP")
|
|
self.PopupNewPGS_txtBirthday.placeholder = Core.Lang.Get(key: "LBL_BIRTHDAY")
|
|
self.PopupNewPGS_txtSampleid.placeholder = Core.Lang.Get(key: "LBL_SAMPLEID")
|
|
self.PopupNewPGS_txtPassword.placeholder = Core.Lang.Get(key: "LBL_PASSWORD")
|
|
self.PopupNewPGS_txtPasswordConfirm.placeholder = Core.Lang.Get(key: "LBL_PASSWORD_CONFIRM")
|
|
self.PopupNewPGS_BtnCancel.setTitle(Core.Lang.Get(key: "BTN_CANCEL"), for: .normal)
|
|
self.PopupNewPGS_BtnAdd.setTitle(Core.Lang.Get(key: "BTN_ADD"), for: .normal)
|
|
self.PopupNewPGS_BtnPrivatePolicy.setTitle(Core.Lang.Get(key: "LBL_PRIVACY_POLICY"), for: .normal)
|
|
self.LBLNORESULTS.text = Core.Lang.Get(key: "LBL_NO_RESULTS")
|
|
|
|
self.PopupPasswordConfirm_BtnCancel.setTitle(Core.Lang.Get(key: "BTN_CANCEL"), for: .normal)
|
|
self.PopupPasswordConfirm_BtnEncrypt.setTitle(Core.Lang.Get(key: "BTN_ENCRYPT"), for: .normal)
|
|
self.PopupPasswordConfirm_txtPassword.placeholder = Core.Lang.Get(key: "LBL_PASSWORD")
|
|
|
|
self.PopupPrivatePolicy_TextLabel.text = Core.Lang.Get(key: "PRIVATE_POLICY_TEXT")
|
|
self.PopupPrivatePolicy_HeadLabel.text = Core.Lang.Get(key: "LBL_PRIVACY_POLICY")
|
|
self.PopupPrivatePolicy_BtnAccept.setTitle(Core.Lang.Get(key: "BTN_ACCEPT_PRIVACY_POLICY"), for: .normal)
|
|
|
|
self.PopupPush_LabelHeader.text = Core.Lang.Get(key: "LBL_PUSH_NOTIFICATION_EXPLAIN_HEADER")
|
|
self.PopupPush_LabelText.text = Core.Lang.Get(key: "MSG_PUSH_NOTIFICATION_EXPLAIN_TEXT")
|
|
self.PopupPush_BtnYes.setTitle(Core.Lang.Get(key: "BTN_OK"), for: .normal)
|
|
}
|
|
|
|
@objc func didTapCheckbox()
|
|
{
|
|
self.PopupPrivatePolicy_Checkbox.toogle()
|
|
}
|
|
|
|
/**
|
|
* Creates the datepicker on the bottom popup menu
|
|
*/
|
|
func createDatePicker()
|
|
{
|
|
let formatter=DateFormatter()
|
|
formatter.dateFormat = "yyyy/MM/dd"
|
|
self.PopupNewPGS_dtBirthday.locale = Locale(identifier: Core.Lang.GetLocale())
|
|
self.PopupNewPGS_dtBirthday.calendar.locale = Locale(identifier: Core.Lang.GetLocale())
|
|
self.PopupNewPGS_dtBirthday.datePickerMode = .date
|
|
self.PopupNewPGS_dtBirthday.preferredDatePickerStyle = .wheels
|
|
self.PopupNewPGS_dtBirthday.date = formatter.date(from: "2000/01/01")!
|
|
self.PopupNewPGS_dtBirthday.maximumDate = Date()
|
|
self.PopupNewPGS_dtBirthday.minimumDate = formatter.date(from: "1900/01/01")
|
|
|
|
let toolbar = UIToolbar()
|
|
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace,
|
|
target: nil, action: nil)
|
|
let doneButton = UIBarButtonItem(title: Core.Lang.Get(key: "BTN_DONE"), style: .done,
|
|
target: self, action: #selector(PopupNewPGS_dtBirthdayDone))
|
|
|
|
toolbar.setItems([flexSpace, doneButton], animated: true)
|
|
toolbar.sizeToFit()
|
|
|
|
self.PopupNewPGS_txtBirthday.inputAccessoryView = toolbar
|
|
self.PopupNewPGS_txtBirthday.inputView = self.PopupNewPGS_dtBirthday
|
|
}
|
|
|
|
//MARK: BEGIN Application Event Bridgs
|
|
|
|
public func onSessionChanged(session: Core.Models.Session)
|
|
{
|
|
//TODO: handle if push permission was taken away-> Show Instruction View that the user has to permitt permissions to push
|
|
}
|
|
|
|
//MARK: END Application Event Bridgs
|
|
|
|
//MARK: BEGIN Events
|
|
|
|
@objc func PopupNewPGS_dtBirthdayDone()
|
|
{
|
|
let dateFormatter = DateFormatter()
|
|
dateFormatter.dateFormat = "dd.MM.yyyy"
|
|
let dt = dateFormatter.string(from: self.PopupNewPGS_dtBirthday.date)
|
|
|
|
self.PopupNewPGS_txtBirthday.text = dt
|
|
self.PopupNewPGS_txtSampleid.becomeFirstResponder()
|
|
}
|
|
|
|
@IBAction func popupPush_BtnYes_Click(_ sender: Any)
|
|
{
|
|
self.PushNotificationAccepted(true)
|
|
}
|
|
|
|
private func PushNotificationAccepted(_ flagAccepted: Bool)
|
|
{
|
|
if (ViewController.Settings == nil)
|
|
{
|
|
ViewController.Settings = Core.Models.Settings()
|
|
}
|
|
ViewController.Settings!.pushNotificationExplained = true
|
|
ViewController.Settings!.pushNotificationAccepted = flagAccepted
|
|
_ = ViewController.Settings!.save(atPath: Core.System.SettingsPath())
|
|
|
|
self.HidePopup(overlay: self.PopupPush_Overlay, content: self.PopupPush_Content)
|
|
|
|
if(flagAccepted)
|
|
{
|
|
self.AskForPushPermissions()
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private func OpenScanner2SelectLabor(_ sender: Any)
|
|
{
|
|
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
|
let scannerController = storyboard.instantiateViewController(identifier: "ScannerController")
|
|
|
|
scannerController.modalPresentationStyle = .fullScreen
|
|
let transition = CATransition()
|
|
transition.duration = 0.25
|
|
transition.type = .push
|
|
transition.subtype = .fromRight
|
|
self.view.window!.layer.add(transition, forKey: kCATransition)
|
|
self.present(scannerController, animated: false)
|
|
}
|
|
|
|
@IBAction func ScanBarcodeClick(_ sender: Any)
|
|
{
|
|
|
|
let scannerController = ScannerViewController.InitScannerController(scanSampleID: true)
|
|
|
|
scannerController.modalPresentationStyle = .fullScreen
|
|
let transition = CATransition()
|
|
transition.duration = 0.25
|
|
transition.type = .push
|
|
transition.subtype = .fromRight
|
|
self.view.window!.layer.add(transition, forKey: kCATransition)
|
|
self.present(scannerController, animated: false)
|
|
}
|
|
|
|
// MARK: ON AddButton Click
|
|
@IBAction func AddButtonClick(_ sender: Any)
|
|
{
|
|
self.PopupNewPGS_Status.text = ""
|
|
self.PopupNewPGS_txtSampleid.text = ""
|
|
self.PopupNewPGS_Loading.isHidden = true
|
|
self.PopupNewPGS_Loading.stopAnimating()
|
|
self.PopupNewPGS_BtnCancel.setTitle(Core.Lang.Get(key: "BTN_CANCEL"), for: .normal)
|
|
|
|
if(ViewController.Settings?.udid != nil)
|
|
{
|
|
if(ViewController.Settings!.zip != nil)
|
|
{
|
|
self.PopupNewPGS_txtZIP.text = ViewController.Settings!.zip
|
|
}
|
|
|
|
if(ViewController.Settings!.birthday != nil)
|
|
{
|
|
self.PopupNewPGS_dtBirthday.date = ViewController.Settings!.GetBirthday()!
|
|
self.PopupNewPGS_txtBirthday.text = ViewController.Settings!.GetFormatedBirthday()!
|
|
}
|
|
|
|
self.PopupNewPGS_BtnAdd.setTitle(Core.Lang.Get(key: "BTN_ADD"), for: .normal)
|
|
self.PopupNewPGS_PGS.frame.origin = CGPoint(x: 0, y: self.PopupNewPGS_PGS.frame.origin.y)
|
|
self.PopupNewPGS_MasterPassword.frame.origin = CGPoint(
|
|
x: self.PopupNewPGS_MasterPassword.frame.width,
|
|
y: self.PopupNewPGS_MasterPassword.frame.origin.y)
|
|
self.PopupNewPGS_MasterPassword.isHidden = true
|
|
}
|
|
else
|
|
{
|
|
self.PopupNewPGS_BtnAdd.setTitle(Core.Lang.Get(key: "BTN_NEXT"), for: .normal)
|
|
}
|
|
|
|
self.PopupNewPGS.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
|
|
self.PopupNewPGS_Overlay.alpha = 0.0
|
|
self.PopupNewPGS_Overlay.isHidden = false
|
|
|
|
UIView.animate(withDuration: 0.24) {
|
|
self.PopupNewPGS.transform = CGAffineTransform.identity
|
|
self.PopupNewPGS_Overlay.alpha = 70.0
|
|
}
|
|
}
|
|
|
|
private func ShowPopup(overlay: UIView!, content: UIView!)
|
|
{
|
|
content.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
|
|
overlay.alpha = 0.0
|
|
overlay.isHidden = false
|
|
|
|
UIView.animate(withDuration: 0.24) {
|
|
content.transform = CGAffineTransform.identity
|
|
overlay.alpha = 70.0
|
|
}
|
|
}
|
|
|
|
private func HidePopup(overlay: UIView!, content: UIView!)
|
|
{
|
|
UIView.animate(withDuration: 0.24, animations: {
|
|
overlay.alpha = 0.0
|
|
content.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
|
|
}) {_ in
|
|
overlay.isHidden = true
|
|
}
|
|
|
|
}
|
|
|
|
private func Ask4PolicyAGBFirstTime()
|
|
{
|
|
if(!(ViewController.Settings?.policyAGBExplained ?? false))
|
|
{
|
|
self.ShowPrivatePolicyInWeb()
|
|
}
|
|
|
|
}
|
|
|
|
private func AskForPushPermissions()
|
|
{
|
|
let center = UNUserNotificationCenter.current()
|
|
center.delegate = self
|
|
|
|
center.requestAuthorization(options: [ .sound,.alert,.badge ])
|
|
{
|
|
(granted, error) in
|
|
|
|
if error == nil
|
|
{
|
|
if (granted)
|
|
{
|
|
AppDelegate.Session.NotificationGranted = true
|
|
DispatchQueue.main.async {
|
|
UIApplication.shared.registerForRemoteNotifications()
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AppDelegate.Session.NotificationGranted = false
|
|
Core.Log.Warning(msg: "User did not grant the permission to the notifications", namespace: "AppDelegate", method: "Initialize")
|
|
}
|
|
|
|
DispatchQueue.main.async
|
|
{
|
|
self.Ask4PolicyAGBFirstTime()
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
AppDelegate.Session.NotificationGranted = false
|
|
Core.Log.Error(err: error!, namespace: "AppDelegate", method: "Initialize")
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// MARK: BEGIN PUSH-Notification delegates
|
|
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (_ options: UNNotificationPresentationOptions) -> Void)
|
|
{
|
|
if(ViewController.CurrentViewController != nil)
|
|
{
|
|
ViewController.CurrentViewController!.loadResults()
|
|
}
|
|
}
|
|
|
|
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void)
|
|
{
|
|
UIApplication.shared.applicationIconBadgeNumber = 1
|
|
}
|
|
|
|
// MARK: END PUSH-Notification delegates
|
|
|
|
//MARK: BEGIN TextField delegates
|
|
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
|
|
{
|
|
let currentString: NSString = textField.text! as NSString
|
|
let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString
|
|
|
|
if(textField == self.PopupNewPGS_txtSampleid)
|
|
{
|
|
let filteredString = string.rangeOfCharacter(from: NSCharacterSet.alphanumerics)
|
|
return newString.length <= 14 && (filteredString != nil || string.count == 0)
|
|
}
|
|
|
|
if(textField == self.PopupNewPGS_txtZIP || textField == self.PopupNewPGS_txtPin)
|
|
{
|
|
let filteredString = string.rangeOfCharacter(from: NSCharacterSet.decimalDigits)
|
|
return newString.length <= 5 && (filteredString != nil || string.count == 0)
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool
|
|
{
|
|
self.PopupNewPGS_Status.text = ""
|
|
|
|
if(textField == self.PopupNewPGS_txtSampleid)
|
|
{
|
|
let dateFormatter = DateFormatter()
|
|
dateFormatter.dateFormat = "dd.MM.yyyy"
|
|
let dt = dateFormatter.string(from: self.PopupNewPGS_dtBirthday.date)
|
|
self.PopupNewPGS_txtBirthday.text = dt
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func textFieldShouldReturn(_ textField: UITextField) -> Bool
|
|
{
|
|
if(textField == self.PopupNewPGS_txtZIP)
|
|
{
|
|
self.PopupNewPGS_txtBirthday.becomeFirstResponder()
|
|
}
|
|
else if(textField == self.PopupNewPGS_txtBirthday)
|
|
{
|
|
self.PopupNewPGS_txtSampleid.becomeFirstResponder()
|
|
}
|
|
else if(textField == self.PopupNewPGS_txtSampleid)
|
|
{
|
|
if(ViewController.Settings?.verificator_hash == nil)
|
|
{
|
|
self.showPasswordArea()
|
|
self.PopupNewPGS_txtPassword.becomeFirstResponder()
|
|
}
|
|
else
|
|
{
|
|
self.view.endEditing(true)
|
|
self.requestPGS()
|
|
}
|
|
}
|
|
else if(textField == self.PopupNewPGS_txtPassword)
|
|
{
|
|
self.PopupNewPGS_txtPasswordConfirm.becomeFirstResponder()
|
|
}
|
|
else if(textField == self.PopupNewPGS_txtPasswordConfirm)
|
|
{
|
|
self.PopupNewPGS_txtPin.becomeFirstResponder()
|
|
}
|
|
else if(textField == self.PopupNewPGS_txtPin)
|
|
{
|
|
self.view.endEditing(true)
|
|
self.requestPGS()
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
//MARK: END TextField delegates
|
|
|
|
@IBAction func PopupNewPGS_BtnCancelClick(_ sender: Any)
|
|
{
|
|
self.view.endEditing(true)
|
|
|
|
if(!self.PopupNewPGS_Loading.isAnimating)
|
|
{
|
|
if(self.PopupNewPGS_MasterPassword.isHidden)
|
|
{
|
|
self.PopupNewPGSHide()
|
|
}
|
|
else
|
|
{
|
|
self.hidePasswordArea()
|
|
}
|
|
}
|
|
}
|
|
|
|
private func PopupNewPGSHide()
|
|
{
|
|
UIView.animate(withDuration: 0.24, animations: {
|
|
self.PopupNewPGS_Overlay.alpha = 0.0
|
|
self.PopupNewPGS.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
|
|
}) {_ in
|
|
self.PopupNewPGS_Overlay.isHidden = true
|
|
}
|
|
}
|
|
|
|
@IBAction func PopupMenuArea_BtnSettingsClick(_ sender: Any)
|
|
{
|
|
self.view.endEditing(true)
|
|
//self.PopupMenuAreaHide()
|
|
|
|
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
|
let settingsController = storyboard.instantiateViewController(identifier: "SettingsController")
|
|
settingsController.modalPresentationStyle = .fullScreen
|
|
let transition = CATransition()
|
|
transition.duration = 0.25
|
|
transition.type = .push
|
|
transition.subtype = .fromRight
|
|
self.view.window!.layer.add(transition, forKey: kCATransition)
|
|
self.present(settingsController, animated: false)
|
|
}
|
|
|
|
|
|
@IBAction func PopupNewPGS_BtnAddClick(_ sender: Any)
|
|
{
|
|
if(ViewController.Settings?.udid != nil)
|
|
{
|
|
self.requestPGS()
|
|
}
|
|
else
|
|
{
|
|
if(self.validatePGSData())
|
|
{
|
|
self.showPasswordArea()
|
|
}
|
|
}
|
|
}
|
|
|
|
@objc func dashedAreaLongPressed(sender: UILongPressGestureRecognizer)
|
|
{
|
|
if(ViewController.Settings?.udid != nil)
|
|
{
|
|
self.loadResults()
|
|
}
|
|
}
|
|
|
|
//MARK: END Events
|
|
|
|
//MARK: BEGIN Functions
|
|
|
|
private func showPasswordArea()
|
|
{
|
|
if(self.PopupNewPGS_MasterPassword.isHidden)
|
|
{
|
|
self.PopupNewPGS_MasterPassword.frame.origin = CGPoint(x: self.PopupNewPGS_MasterPassword.frame.width, y: self.PopupNewPGS_MasterPassword.frame.origin.y)
|
|
self.PopupNewPGS_MasterPassword.isHidden = false
|
|
|
|
UIView.animate(withDuration: 0.24, animations: {
|
|
self.PopupNewPGS_PGS.frame.origin = CGPoint(x: -self.PopupNewPGS_PGS.frame.width, y: self.PopupNewPGS_PGS.frame.origin.y)
|
|
self.PopupNewPGS_MasterPassword.frame.origin = CGPoint(x: 0, y: self.PopupNewPGS_MasterPassword.frame.origin.y)
|
|
}) {_ in
|
|
|
|
self.PopupNewPGS_BtnCancel.setTitle(Core.Lang.Get(key: "BTN_BACK"), for: .normal)
|
|
self.PopupNewPGS_BtnAdd.setTitle(Core.Lang.Get(key: "BTN_REGISTER"), for: .normal)
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self.requestPGS()
|
|
}
|
|
}
|
|
|
|
@IBAction func PopupPrivatePolicy_BtnAcceptClick(_ sender: Any)
|
|
{
|
|
self.HidePrivatePolicy()
|
|
}
|
|
|
|
@IBAction func PopupPrivatePolicy_BtnAddClick(_ sender: Any)
|
|
{
|
|
self.ShowPrivatePolicyInWeb()
|
|
}
|
|
|
|
|
|
private func getLocalPolicyLink() -> String
|
|
{
|
|
let baseURL = Bundle.main.path(forResource: "privacy_policy", ofType: "html")
|
|
return baseURL ?? ""
|
|
}
|
|
|
|
private func ShowPrivatePolicyInWeb()
|
|
{
|
|
guard let url = URL(string: Core.Lang.Get(key: "AGB_POLICY_LINK")) else {
|
|
return
|
|
}
|
|
let localUrl = URL(string: getLocalPolicyLink()) ?? url
|
|
|
|
let vc = WebViewController(url: url, title: Core.Lang.Get(key: "BTN_ACCEPT_PRIVACY_POLICY"), localUrl: localUrl)
|
|
vc.parentView = self
|
|
let navVC = UINavigationController(rootViewController: vc)
|
|
present(navVC, animated: true)
|
|
}
|
|
|
|
|
|
private func ShowPrivatePolicy()
|
|
{
|
|
self.PopupPrivatePolicy_Overlay.alpha = 100
|
|
self.PopupPrivatePolicy_Overlay.isHidden = false
|
|
|
|
UIView.animate(withDuration: 0.24, animations: {
|
|
self.PopupNewPGS_Overlay.frame.origin = CGPoint(x: -self.PopupNewPGS_Overlay.frame.width, y: self.PopupNewPGS_Overlay.frame.origin.y)
|
|
self.PopupPrivatePolicy.frame.origin = CGPoint(x: 0, y: self.PopupPrivatePolicy.frame.origin.y)
|
|
})
|
|
}
|
|
|
|
private func HidePrivatePolicy()
|
|
{
|
|
self.PopupPrivatePolicy_Checkbox.setChecked(flag: true)
|
|
|
|
UIView.animate(withDuration: 0.24, animations: {
|
|
self.PopupNewPGS_Overlay.frame.origin = CGPoint(x: 0, y: self.PopupNewPGS_Overlay.frame.origin.y)
|
|
self.PopupPrivatePolicy.frame.origin = CGPoint(x: self.PopupPrivatePolicy.frame.width, y: self.PopupPrivatePolicy.frame.origin.y)
|
|
|
|
}) {_ in
|
|
self.PopupPrivatePolicy_Overlay.isHidden = true
|
|
self.PopupNewPGS_Overlay.isHidden = false
|
|
}
|
|
}
|
|
|
|
|
|
private func hidePasswordArea()
|
|
{
|
|
UIView.animate(withDuration: 0.24, animations: {
|
|
self.PopupNewPGS_PGS.frame.origin = CGPoint(x: 0, y: self.PopupNewPGS_PGS.frame.origin.y)
|
|
self.PopupNewPGS_MasterPassword.frame.origin = CGPoint(x: self.PopupNewPGS_MasterPassword.frame.width, y: self.PopupNewPGS_MasterPassword.frame.origin.y)
|
|
}) {_ in
|
|
self.PopupNewPGS_MasterPassword.isHidden = true
|
|
self.PopupNewPGS_BtnCancel.setTitle(Core.Lang.Get(key: "BTN_CANCEL"), for: .normal)
|
|
self.PopupNewPGS_BtnAdd.setTitle(Core.Lang.Get(key: "BTN_NEXT"), for: .normal)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load results from the database and from the outside service
|
|
* @param onlyLocale - if true it will load only from locale db
|
|
*/
|
|
public func loadResults(onlyLocale: Bool = false)
|
|
{
|
|
//if password is not defined than don't make any results loading
|
|
if (AppDelegate.Session.DevicePassword == nil)
|
|
{
|
|
return
|
|
}
|
|
|
|
if(!self.LoadingData)
|
|
{
|
|
self.LoadingData = true
|
|
|
|
self.dbResults = Core.Database.Results.GetResults()
|
|
|
|
let resultsAvailable = self.dbResults != nil && self.dbResults!.count > 0
|
|
|
|
self.LBLNORESULTS.isHidden = resultsAvailable
|
|
self.ResultsTable.isHidden = !resultsAvailable
|
|
|
|
self.ResultsTable.reloadData()
|
|
|
|
UIApplication.shared.applicationIconBadgeNumber = 0
|
|
|
|
if(!onlyLocale)
|
|
{
|
|
self.MainLoadingShow()
|
|
|
|
//MARK: Load from serverhttps://stackoverflow.com/questions/24190277/writing-handler-for-uialertaction
|
|
let getOpened = Core.Models.Request.GetOpened()
|
|
getOpened.udid = AppDelegate.Session.Device!.udid
|
|
getOpened.verificator_hash = ViewController.Settings!.verificator_hash
|
|
|
|
let requestKeyPair = Core.Security.Curve25519.GenerateKeyPair()
|
|
let currentHost = (ViewController.Settings!.labor?.host ?? .DEVELOPMENT)
|
|
|
|
Core.Https.Request.KeyExchangeAsync(host: currentHost, keyPair: requestKeyPair,
|
|
onSuccess: {
|
|
publicKey in
|
|
|
|
let sharedKey = requestKeyPair.GetSharedKey(peerPublicKeyBase64: publicKey.key)
|
|
let encryptedRequest = Core.Models.Request.EncryptedRequest(descriptor: "GetOpened", contentObject: getOpened, requestType: .REQUEST_GET_OPENED, key: sharedKey!)
|
|
|
|
Core.Https.Request.EncryptedRequestAsync(host: currentHost, controller: "results", action: "opened", request: encryptedRequest, serverPublicKey: publicKey, keyPair: requestKeyPair, onSuccess: {
|
|
|
|
encryptedResponse in
|
|
|
|
let status = encryptedResponse.Decrypt(key: sharedKey!) as? Array<Core.Models.Database.Status>
|
|
|
|
self.dbResults = Core.Database.Results.GetResults(activeOnly: false)
|
|
|
|
if(status != nil && status!.count > 0)
|
|
{
|
|
//MARK: Check if new requests or update
|
|
for i in 0...(status!.count-1)
|
|
{
|
|
let s = status![i]
|
|
let statusText = s.results_status?.lowercased() ?? ""
|
|
let results = s.ToResults()
|
|
|
|
if(statusText.count > 0 && statusText != "none")
|
|
{
|
|
if(statusText == "not_found")
|
|
{
|
|
_ = Core.Database.Results.Delete(results: results)
|
|
|
|
DispatchQueue.main.async
|
|
{
|
|
self.ShowMessagePopup(title: "", message: Core.Lang.Get(key: "MSG_REQUESTED_RESULTS_NOT_FOUND"))
|
|
}
|
|
|
|
}
|
|
else if (statusText == "rejected")
|
|
{
|
|
DispatchQueue.main.async
|
|
{
|
|
self.ShowMessagePopup(title: "", message: Core.Lang.Get(key: "MSG_REQUESTED_RESULTS_REJECTED"))
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if(!self.dbResults!.contains(where: { $0.pgs == s.pgs }))
|
|
{
|
|
if(!Core.Database.Results.Create(results: results))
|
|
{
|
|
Core.Log.Error(msg: "could not create results in db", namespace: "ViewController", method: "loadResults")
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!Core.Database.Results.Update(results: results))
|
|
{
|
|
Core.Log.Error(msg: "could not update results in db", namespace: "ViewController", method: "loadResults")
|
|
}
|
|
}
|
|
|
|
self.dbResults = Core.Database.Results.GetResults()
|
|
|
|
DispatchQueue.main.async
|
|
{
|
|
let resultsAvailable = self.dbResults != nil && self.dbResults!.count > 0
|
|
|
|
self.LBLNORESULTS.isHidden = resultsAvailable
|
|
self.ResultsTable.isHidden = !resultsAvailable
|
|
|
|
self.ResultsTable.reloadData()
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DispatchQueue.main.async
|
|
{
|
|
self.MainLoadingHide()
|
|
}
|
|
|
|
self.LoadingData = false
|
|
},
|
|
onError: {
|
|
error in
|
|
Core.Log.Error(msg: error, namespace: "ViewController", method: "loadResults")
|
|
self.LoadingData = false
|
|
|
|
DispatchQueue.main.async
|
|
{
|
|
self.MainLoadingHide()
|
|
}
|
|
})
|
|
},
|
|
onError: {
|
|
error in
|
|
self.LoadingData = false
|
|
|
|
Core.Log.Error(msg: error, namespace: "ViewController", method: "loadResults")
|
|
|
|
DispatchQueue.main.async
|
|
{
|
|
if(AppDelegate.Session.Maintenance && !AppDelegate.Session.MaintenanceNotified)
|
|
{
|
|
AppDelegate.Session.MaintenanceNotified = true
|
|
self.ShowMessagePopup(title: "Fehler", message: Core.Lang.Get(key: "MSG_MAINTENANCE"))
|
|
}
|
|
self.MainLoadingHide()
|
|
}
|
|
})
|
|
}
|
|
else
|
|
{
|
|
self.LoadingData = false
|
|
}
|
|
}
|
|
}
|
|
|
|
private func validatePGSData() -> Bool
|
|
{
|
|
if(!self.PopupNewPGS_Loading.isAnimating)
|
|
{
|
|
self.PopupNewPGS_ShowLoading()
|
|
|
|
let zipText = self.PopupNewPGS_txtZIP.text ?? ""
|
|
let birthdayText = self.PopupNewPGS_txtBirthday.text ?? ""
|
|
let sampleidText = self.PopupNewPGS_txtSampleid.text ?? ""
|
|
|
|
if(zipText.count==0)
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_ENTER_ZIP"))
|
|
//self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_ALREADY_SUBSCRIBTED"))
|
|
}
|
|
else if(birthdayText.count == 0)
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_ENTER_BIRTHDAY"))
|
|
}
|
|
else if(sampleidText.count == 0)
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_ENTER_SAMPLEID"))
|
|
}
|
|
else if(zipText.count < 4)
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_ENTER_VALID_ZIP"))
|
|
}
|
|
else if(birthdayText.count < 10 )
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_ENTER_VALID_BIRTHDAY"))
|
|
}
|
|
else if(sampleidText.count < 6 || sampleidText.count > 14)
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_ENTER_VALID_SAMPLEID"))
|
|
}
|
|
else
|
|
{
|
|
self.PopupNewPGS_HideLoading()
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
private func validateRegistrationData() -> Bool
|
|
{
|
|
if(!self.PopupNewPGS_Loading.isAnimating)
|
|
{
|
|
self.PopupNewPGS_ShowLoading()
|
|
|
|
let pinText = self.PopupNewPGS_txtPin.text ?? ""
|
|
let passwordText = self.PopupNewPGS_txtPassword.text ?? ""
|
|
|
|
if(passwordText.count == 0)
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_ENTER_PASSWORD"))
|
|
}
|
|
else
|
|
{
|
|
if(!Core.Models.Request.ChangeVerificatorHashProvider.IsPasswordStrong(password: passwordText))
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_ENTER_STRONG_PASSWORD"))
|
|
}
|
|
else if(self.PopupNewPGS_txtPassword.text != self.PopupNewPGS_txtPasswordConfirm.text)
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_PASSWORD_MISMATCH"))
|
|
}
|
|
else if(pinText.count == 0)
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_ENTER_PIN"))
|
|
}
|
|
else if(pinText.count != 5)
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_PIN_LENGTH"))
|
|
}
|
|
else if(!self.PopupPrivatePolicy_Checkbox.IsChecked())
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_ACCEPT_PRIVACY_POLICY"))
|
|
}
|
|
else
|
|
{
|
|
self.PopupNewPGS_HideLoading()
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
/**
|
|
* Send PGS Request to the server
|
|
*/
|
|
private func requestPGS()
|
|
{
|
|
self.PopupNewPGS_Status.text = ""
|
|
|
|
let zipText = self.PopupNewPGS_txtZIP.text ?? ""
|
|
let birthdayText = self.PopupNewPGS_txtBirthday.text ?? ""
|
|
let sampleidText = self.PopupNewPGS_txtSampleid.text ?? ""
|
|
let pinText = self.PopupNewPGS_txtPin.text ?? ""
|
|
let passwordText = self.PopupNewPGS_txtPassword.text ?? ""
|
|
|
|
if(self.validatePGSData())
|
|
{
|
|
//First installation
|
|
if(ViewController.Settings?.udid == nil)
|
|
{
|
|
if(self.validateRegistrationData())
|
|
{
|
|
self.PopupNewPGS_ShowLoading()
|
|
|
|
let encryptionKeyPair = Core.Security.Curve25519.GenerateKeyPair()
|
|
|
|
if(encryptionKeyPair.PrivateKey != nil && encryptionKeyPair.PublicKey != nil)
|
|
{
|
|
if (ViewController.Settings == nil) {
|
|
ViewController.Settings = Core.Models.Settings()
|
|
}
|
|
|
|
AppDelegate.Session.DevicePassword = passwordText
|
|
let pwdKey = Core.Security.AES.GetKey(password: passwordText)
|
|
let pwdKeyString = String(decoding: pwdKey, as: UTF8.self)
|
|
ViewController.Settings!.public_key = encryptionKeyPair.PublicKey!
|
|
let pwd_reset_hash = NSUUID().uuidString
|
|
ViewController.Settings!.password_reset_hash = pwd_reset_hash
|
|
let passwordHashKey = Core.Security.AES.GetKey(password: pwd_reset_hash + pinText)
|
|
let pwdHash = Core.Security.AES.Encrypt(value: passwordText, password: String(decoding: passwordHashKey, as: UTF8.self))
|
|
ViewController.Settings!.password_hash = pwdHash
|
|
ViewController.Settings!.verificator_hash = Core.Security.SHA512.HMAC(message: Core.Security.SHA512.VerificatorHashingValue.data(using: .utf8)!, key: pwdKeyString)
|
|
|
|
ViewController.Settings!.hashed_private_key = Core.Security.AES.Encrypt(value: encryptionKeyPair.PrivateKey!, password: pwdKeyString)
|
|
|
|
ViewController.Settings!.zip = zipText
|
|
ViewController.Settings!.SetBirthday(date: PopupNewPGS_dtBirthday.date)
|
|
ViewController.Settings!.udid = AppDelegate.Session.Device!.udid
|
|
|
|
if(!ViewController.Settings!.save(atPath: Core.System.SettingsPath()))
|
|
{
|
|
PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_COULD_NOT_SAVE"))
|
|
Core.Log.Critical(msg: "Could not save settings to the file", namespace: "ViewController", method: "requestPGS")
|
|
}
|
|
else
|
|
{
|
|
ViewController.Settings = Core.Models.Settings.loadFromFile(atPath: Core.System.SettingsPath())
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_ENCRYPTION_NOT_SUPPORTED"))
|
|
Core.Log.Critical(msg: "Could not create Curve25519 keyPair", namespace: "ViewController", method: "requestPGS")
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ViewController.Settings!.zip = zipText
|
|
ViewController.Settings!.SetBirthday(date: PopupNewPGS_dtBirthday.date)
|
|
|
|
if(!ViewController.Settings!.save(atPath: Core.System.SettingsPath()))
|
|
{
|
|
PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_COULD_NOT_SAVE"))
|
|
Core.Log.Critical(msg: "Could not save settings to the file", namespace: "ViewController", method: "requestPGS")
|
|
}
|
|
}
|
|
|
|
// User has password already defined
|
|
if(ViewController.Settings?.udid != nil)
|
|
{
|
|
self.PopupNewPGS_ShowLoading()
|
|
|
|
let dateFormatter = DateFormatter()
|
|
dateFormatter.dateFormat = "yyyy-MM-dd"
|
|
let birthday = dateFormatter.string(from: self.PopupNewPGS_dtBirthday.date)
|
|
|
|
let subscribe = Core.Models.Request.Subscribe()
|
|
subscribe.udid = AppDelegate.Session.Device!.udid
|
|
subscribe.device_token = AppDelegate.Session.Device!.token
|
|
subscribe.pgs = Core.Security.SHA512.Encrypt(data: (zipText + birthday + sampleidText).data(using: .utf8)!)
|
|
let pwd = Core.Security.AES.GetKey(password: subscribe.udid! + Core.Security.AES.PGS_ENCRYPT_PARTIAL_KEY)
|
|
subscribe.pgs_hash = Core.Security.AES.Encrypt(value: (zipText + "|" + birthday + "|" + sampleidText), password: String(decoding:pwd, as: UTF8.self))!
|
|
subscribe.client_public_key = ViewController.Settings!.public_key
|
|
subscribe.device_type = 1
|
|
subscribe.verificator_hash = ViewController.Settings!.verificator_hash
|
|
subscribe.pin = pinText
|
|
|
|
if(subscribe.pin?.isEmpty ?? true)
|
|
{
|
|
subscribe.pin = String(Int.random(in: 10000..<99999))
|
|
}
|
|
|
|
let dbResults = Core.Database.Results.GetResults(pgs: subscribe.pgs!)
|
|
|
|
if(dbResults != nil)
|
|
{
|
|
let status = dbResults?.GetStatus()
|
|
|
|
if(status == .COMPLETED)
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "MSG_PGS_ALREADY_EXISTS"))
|
|
}
|
|
else
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "MSG_PGS_RESPONSE_PENDING"))
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self.hideKeyboard()
|
|
|
|
let requestKeyPair = Core.Security.Curve25519.GenerateKeyPair()
|
|
let currentHost = (ViewController.Settings!.labor?.host ?? .DEVELOPMENT)
|
|
|
|
Core.Https.Request.KeyExchangeAsync(host: currentHost, keyPair: requestKeyPair,
|
|
onSuccess: {
|
|
publicKey in
|
|
|
|
let sharedKey = requestKeyPair.GetSharedKey(peerPublicKeyBase64: publicKey.key)
|
|
let encryptedRequest = Core.Models.Request.EncryptedRequest(descriptor: "Subscribe", contentObject: subscribe, requestType: .REQUEST_SUBSCRIBE, key: sharedKey!)
|
|
|
|
Core.Https.Request.EncryptedRequestAsync(host: currentHost, controller: "results", action: "subscribe", request: encryptedRequest, serverPublicKey: publicKey, keyPair: requestKeyPair, onSuccess: {
|
|
|
|
encryptedResponse in
|
|
|
|
let response = encryptedResponse.Decrypt(key: sharedKey!)
|
|
|
|
DispatchQueue.main.async
|
|
{
|
|
if(encryptedResponse.descriptor!.lowercased() == "success")
|
|
{
|
|
if(Core.Database.Results.Create(results: subscribe.ToResults()))
|
|
{
|
|
self.PopupNewPGS_HideLoading()
|
|
self.ShowMessagePopup(title: "Vielen Dank", message: Core.Lang.Get(key: "MSG_PGS_SUCCESSFULLY_CREATED"))
|
|
self.loadResults()
|
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1)
|
|
{
|
|
self.PopupNewPGSHide()
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_COULD_NOT_SAVE"))
|
|
Core.Log.Critical(msg: "Could not save results to the database", namespace: "ViewController", method: "requestPGS")
|
|
}
|
|
}
|
|
else if(encryptedResponse.descriptor!.lowercased() == "status")
|
|
{
|
|
let status = (response as? Core.Models.Database.Status)
|
|
|
|
if(status == nil || !Core.Database.Results.CreateOrUpdate(results: status!.ToResults()))
|
|
{
|
|
Core.Log.Critical(msg: "Could not update status in the database", namespace: "ViewController", method: "requestPGS")
|
|
}
|
|
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "MSG_PGS_ALREADY_AVAILABLE"))
|
|
self.loadResults()
|
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1)
|
|
{
|
|
self.PopupNewPGSHide()
|
|
}
|
|
}
|
|
else
|
|
{
|
|
let responseException = (response as? Core.Models.Response.Exception)
|
|
|
|
if(responseException != nil)
|
|
{
|
|
switch(responseException!.error_type)
|
|
{
|
|
case Core.Models.Response.Exception.Types.MaxOpenedRequestLimit :
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_MAX_OPENED_REQUEST_LIMIT"))
|
|
|
|
case Core.Models.Response.Exception.Types.AlreadySubscribted:
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_ALREADY_SUBSCRIBTED"))
|
|
|
|
default:
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_COULD_NOT_REGISTER_PGS"))
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: Core.Lang.Get(key: "ERROR_COULD_NOT_REGISTER_PGS"))
|
|
Core.Log.Critical(msg: "Could not register", namespace: "ViewController", method: "requestPGS")
|
|
}
|
|
}
|
|
}
|
|
},
|
|
onError: {
|
|
error in
|
|
|
|
DispatchQueue.main.async
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: error)
|
|
Core.Log.Critical(msg: "Server not reachable", namespace: "ViewController", method: "requestPGS")
|
|
}
|
|
})
|
|
},
|
|
onError: {
|
|
error in
|
|
DispatchQueue.main.async
|
|
{
|
|
self.PopupNewPGS_HideLoading(message: error)
|
|
Core.Log.Critical(msg: "Server not reachable", namespace: "ViewController", method: "requestPGS")
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private func PopupNewPGS_ShowLoading()
|
|
{
|
|
self.PopupNewPGS_Loading.isHidden = false
|
|
self.PopupNewPGS_Loading.startAnimating()
|
|
self.PopupNewPGS_Status.text = ""
|
|
self.PopupNewPGS_Status.isHidden = true
|
|
}
|
|
|
|
private func PopupNewPGS_HideLoading(message: String? = nil)
|
|
{
|
|
self.PopupNewPGS_Loading.isHidden = true
|
|
self.PopupNewPGS_Loading.stopAnimating()
|
|
|
|
if(message != nil)
|
|
{
|
|
self.PopupNewPGS_Status.text = message!
|
|
self.PopupNewPGS_Status.isHidden = false
|
|
}
|
|
}
|
|
|
|
private func PopupPasswordConfirm_ShowLoading()
|
|
{
|
|
self.PopupPasswordConfirm_Loading.isHidden = false
|
|
self.PopupPasswordConfirm_Loading.startAnimating()
|
|
self.PopupPasswordConfirm_Status.text = ""
|
|
self.PopupPasswordConfirm_Status.isHidden = true
|
|
}
|
|
|
|
private func PopupPasswordConfirm_HideLoading(message: String? = nil)
|
|
{
|
|
self.PopupPasswordConfirm_Loading.isHidden = true
|
|
self.PopupPasswordConfirm_Loading.stopAnimating()
|
|
|
|
if(message != nil)
|
|
{
|
|
self.PopupPasswordConfirm_Status.text = message!
|
|
self.PopupPasswordConfirm_Status.isHidden = false
|
|
}
|
|
}
|
|
|
|
|
|
private func MainLoadingHide()
|
|
{
|
|
self.MainLoading.stopAnimating()
|
|
self.MainLoading.isHidden = true
|
|
self.ResultsTableRefresher.endRefreshing()
|
|
}
|
|
|
|
private func MainLoadingShow()
|
|
{
|
|
self.MainLoading.startAnimating()
|
|
self.MainLoading.isHidden = false
|
|
}
|
|
|
|
//MARK: END Functions
|
|
|
|
//MARK: BEGIN TABLE FUNCTIONS
|
|
@objc func tableRefresh(_ sender: Any)
|
|
{
|
|
self.loadResults()
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
|
|
{
|
|
return 70.0
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
|
|
{
|
|
let cell = tableView.dequeueReusableCell(withIdentifier: ResultsTableViewCell.identifier, for: indexPath) as! ResultsTableViewCell
|
|
|
|
if(self.dbResults != nil && self.dbResults!.count > 0 && indexPath.row >= 0 && indexPath.row < self.dbResults!.count)
|
|
{
|
|
let result = self.dbResults![indexPath.row]
|
|
cell.title.text = result.GetFormatedCreatedDate()
|
|
cell.subtitle.text = result.GetStatusText()
|
|
cell.identifier.text = result.pgs!
|
|
cell.icon.setImage(result.GetStatusIcon(), for: .normal)
|
|
cell.icon.tag = indexPath.row
|
|
|
|
if(cell.icon.allTargets.count > 0)
|
|
{
|
|
cell.icon.removeTarget(nil, action: nil, for: .allEvents)
|
|
}
|
|
|
|
cell.icon.addTarget(self, action: #selector(onTableRowIconClick), for: .touchUpInside)
|
|
|
|
cell.separatorInset = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15)
|
|
cell.icon.isUserInteractionEnabled = true
|
|
|
|
cell.selectionStyle = .default;
|
|
let bgView = UIView()
|
|
bgView.backgroundColor = .clear
|
|
cell.selectedBackgroundView = bgView
|
|
|
|
// MARK: Very dirty to start auto download here but for now no chance to do other way
|
|
// because we need to change the icon of the row
|
|
if(result.GetStatus() == .COMPLETED && result.available && !result.picked_up && !self.CurrentDownloadProcessing && AppDelegate.Session.Device!.token != nil)
|
|
{
|
|
let gifLoading = UIImage.gifImageWithName("ic_downloading")
|
|
cell.icon.setImage(gifLoading, for: .normal)
|
|
cell.subtitle.text = Core.Lang.Get(key: "LBL_DOWNLOADING")
|
|
|
|
// Download in background
|
|
DispatchQueue.global(qos: .background).async
|
|
{
|
|
self.downloadResults(results: result, button: cell.icon, show: false)
|
|
}
|
|
}
|
|
}
|
|
|
|
return cell
|
|
}
|
|
|
|
|
|
func numberOfSections(in tableView: UITableView) -> Int
|
|
{
|
|
return 1
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
|
|
{
|
|
return (self.dbResults != nil ? self.dbResults!.count : 0)
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String?
|
|
{
|
|
return Core.Lang.Get(key: "BTN_DELETE")
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath)
|
|
{
|
|
if editingStyle == .delete
|
|
{
|
|
if(self.dbResults != nil && self.dbResults!.count > 0 && indexPath.row >= 0 && indexPath.row < self.dbResults!.count && !self.CurrentDownloadProcessing)
|
|
{
|
|
let result = self.dbResults![indexPath.row]
|
|
|
|
if(Core.Database.Results.Delete(results: result))
|
|
{
|
|
self.loadResults(onlyLocale: true)
|
|
self.deleteOnServer(results: result)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//MARK: END TABLE FUNCTIONS
|
|
|
|
//MARK: BEGIN Download & PDF FUNCTIONS
|
|
@objc func onTableRowIconClick(sender: UIButton)
|
|
{
|
|
let button = sender as UIButton
|
|
|
|
if(self.dbResults != nil && self.dbResults!.count > 0 && button.tag >= 0 && button.tag < self.dbResults!.count && !self.CurrentDownloadProcessing)
|
|
{
|
|
let results = self.dbResults![button.tag]
|
|
|
|
if(results.GetStatus() == .COMPLETED && results.available && !results.picked_up && !self.CurrentDownloadProcessing)
|
|
{
|
|
let gifLoading = UIImage.gifImageWithName("ic_downloading")
|
|
sender.setImage(gifLoading, for: .normal)
|
|
|
|
self.downloadResults(results: results, button: button)
|
|
}
|
|
else if(results.GetStatus() == .COMPLETED && results.available && results.picked_up)
|
|
{
|
|
self.encryptPDF(results: results)
|
|
}
|
|
}
|
|
}
|
|
|
|
//MARK: send the download request to the server
|
|
private func downloadResults(results: Core.Models.Database.Results, button: UIButton!, show: Bool = true)
|
|
{
|
|
self.CurrentDownloadProcessing = true
|
|
|
|
let subscribe = Core.Models.Request.Subscribe()
|
|
subscribe.udid = AppDelegate.Session.Device!.udid
|
|
subscribe.device_token = AppDelegate.Session.Device!.token!
|
|
subscribe.pgs = results.pgs
|
|
subscribe.client_public_key = ViewController.Settings!.public_key
|
|
subscribe.verificator_hash = ViewController.Settings!.verificator_hash
|
|
|
|
self.MainLoadingShow()
|
|
|
|
let requestKeyPair = Core.Security.Curve25519.GenerateKeyPair()
|
|
|
|
let currentHost = ViewController.Settings!.labor?.host ?? .DEVELOPMENT
|
|
|
|
Core.Https.Request.KeyExchangeAsync(host: currentHost, keyPair: requestKeyPair,
|
|
onSuccess: {
|
|
publicKey in
|
|
|
|
let sharedKey = requestKeyPair.GetSharedKey(peerPublicKeyBase64: publicKey.key)
|
|
let encryptedRequest = Core.Models.Request.EncryptedRequest(descriptor: "Subscribe", contentObject: subscribe, requestType: .REQUEST_SUBSCRIBE, key: sharedKey!)
|
|
|
|
Core.Https.Request.EncryptedRequestAsync(host: currentHost, controller: "results", action: "download", request: encryptedRequest, serverPublicKey: publicKey, keyPair: requestKeyPair, onSuccess: {
|
|
|
|
encryptedResponse in
|
|
|
|
self.CurrentDownload = encryptedResponse.Decrypt(key: sharedKey!) as? Core.Models.Response.Download
|
|
|
|
if(self.CurrentDownload != nil)
|
|
{
|
|
self.CurrentDownloadResults = results
|
|
|
|
DispatchQueue.main.async
|
|
{
|
|
if(button != nil)
|
|
{
|
|
button.setImage(results.GetStatusIcon(), for: .normal)
|
|
}
|
|
|
|
self.processEncryption(show: show)
|
|
self.MainLoadingHide()
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DispatchQueue.main.async
|
|
{
|
|
self.MainLoadingHide()
|
|
}
|
|
}
|
|
|
|
self.CurrentDownloadProcessing = false
|
|
},
|
|
onError: {
|
|
error in
|
|
self.CurrentDownloadProcessing = false
|
|
|
|
Core.Log.Error(msg: error, namespace: "ViewController", method: "downloadResults")
|
|
|
|
DispatchQueue.main.async
|
|
{
|
|
self.MainLoadingHide()
|
|
}
|
|
})
|
|
},
|
|
onError: {
|
|
error in
|
|
Core.Log.Error(msg: error, namespace: "ViewController", method: "downloadResults")
|
|
|
|
self.CurrentDownloadProcessing = false
|
|
|
|
DispatchQueue.main.async
|
|
{
|
|
self.MainLoadingHide()
|
|
}
|
|
})
|
|
}
|
|
|
|
//MARK: User has to confirm always decryption of encrypted results by master password
|
|
private func encryptPDF(results: Core.Models.Database.Results)
|
|
{
|
|
if(results.GetStatus() == .COMPLETED && results.available && results.picked_up)
|
|
{
|
|
self.CurrentDownload = nil
|
|
self.CurrentDownloadResults = results
|
|
//showPasswordConfirm()
|
|
self.processEncryption()
|
|
|
|
}
|
|
}
|
|
|
|
//MARK: send pickedup checksum to the file
|
|
private func sendPickedUp(checksum: Core.Models.Request.CheckFileChecksum)
|
|
{
|
|
self.MainLoadingShow()
|
|
|
|
let requestKeyPair = Core.Security.Curve25519.GenerateKeyPair()
|
|
let currentHost = ViewController.Settings!.labor?.host ?? .DEVELOPMENT
|
|
|
|
Core.Https.Request.KeyExchangeAsync(host: currentHost, keyPair: requestKeyPair,
|
|
onSuccess: {
|
|
publicKey in
|
|
|
|
let sharedKey = requestKeyPair.GetSharedKey(peerPublicKeyBase64: publicKey.key)
|
|
let encryptedRequest = Core.Models.Request.EncryptedRequest(descriptor: "CheckFileChecksum", contentObject: checksum, requestType: .REQUEST_CHECKSUM, key: sharedKey!)
|
|
|
|
Core.Https.Request.EncryptedRequestAsync(host: currentHost, controller: "results", action: "pickedup", request: encryptedRequest, serverPublicKey: publicKey, keyPair: requestKeyPair, onError: {
|
|
error in
|
|
Core.Log.Error(msg: error, namespace: "ViewController", method: "sendPickedUp")
|
|
})
|
|
|
|
DispatchQueue.main.async
|
|
{
|
|
self.MainLoadingHide()
|
|
}
|
|
|
|
}, onError: {
|
|
error in
|
|
Core.Log.Error(msg: error, namespace: "ViewController", method: "sendPickedUp")
|
|
})
|
|
}
|
|
|
|
//MARK: deletes results on the server
|
|
private func deleteOnServer(results: Core.Models.Database.Results)
|
|
{
|
|
self.MainLoadingShow()
|
|
|
|
let requestKeyPair = Core.Security.Curve25519.GenerateKeyPair()
|
|
let currentHost = ViewController.Settings!.labor?.host ?? .DEVELOPMENT
|
|
|
|
Core.Https.Request.KeyExchangeAsync(host: currentHost, keyPair: requestKeyPair,
|
|
onSuccess: {
|
|
publicKey in
|
|
|
|
let subscribe = Core.Models.Request.Subscribe()
|
|
subscribe.udid = AppDelegate.Session.Device!.udid
|
|
subscribe.device_token = AppDelegate.Session.Device!.token!
|
|
subscribe.pgs = results.pgs
|
|
subscribe.client_public_key = ViewController.Settings!.public_key
|
|
subscribe.verificator_hash = ViewController.Settings!.verificator_hash
|
|
|
|
let sharedKey = requestKeyPair.GetSharedKey(peerPublicKeyBase64: publicKey.key)
|
|
let encryptedRequest = Core.Models.Request.EncryptedRequest(descriptor: "Subscribe", contentObject: subscribe, requestType: .REQUEST_SUBSCRIBE, key: sharedKey!)
|
|
|
|
Core.Https.Request.EncryptedRequestAsync(host: currentHost, controller: "results", action: "unsubscribe", request: encryptedRequest, serverPublicKey: publicKey, keyPair: requestKeyPair, onError: {
|
|
error in
|
|
Core.Log.Error(msg: error, namespace: "ViewController", method: "deleteOnServer")
|
|
})
|
|
|
|
DispatchQueue.main.async
|
|
{
|
|
self.MainLoadingHide()
|
|
}
|
|
},
|
|
onError: {
|
|
error in
|
|
Core.Log.Error(msg: error, namespace: "ViewController", method: "deleteOnServer")
|
|
})
|
|
}
|
|
|
|
private func showPasswordConfirm()
|
|
{
|
|
self.PopupPasswordConfirm_txtPassword.text = ""
|
|
self.PopupPasswordConfirm_HideLoading(message: Core.Lang.Get(key: "ERROR_ENTER_PASSWORD"))
|
|
|
|
self.PopupPasswordConfirm.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
|
|
self.PopupPasswordConfirm_Overlay.alpha = 0.0
|
|
self.PopupPasswordConfirm_Overlay.isHidden = false
|
|
|
|
UIView.animate(withDuration: 0.24) {
|
|
self.PopupPasswordConfirm.transform = CGAffineTransform.identity
|
|
self.PopupPasswordConfirm_Overlay.alpha = 70.0
|
|
}
|
|
}
|
|
|
|
private func hidePasswordConfirm()
|
|
{
|
|
self.view.endEditing(true)
|
|
|
|
if(!self.PopupPasswordConfirm_Loading.isAnimating)
|
|
{
|
|
UIView.animate(withDuration: 0.24, animations: {
|
|
self.PopupPasswordConfirm_Overlay.alpha = 0.0
|
|
self.PopupPasswordConfirm.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
|
|
}) {_ in
|
|
self.PopupPasswordConfirm_Overlay.isHidden = true
|
|
}
|
|
}
|
|
}
|
|
|
|
//MARK: download encrypted results from the server and let them user decrypt it over password confirmation popup
|
|
private func encryptDownload(show: Bool = true)
|
|
{
|
|
if(self.CurrentDownload != nil)
|
|
{
|
|
let decryptedPrivateKey = Core.Security.AES.Decrypt(value: ViewController.Settings!.hashed_private_key!, password: AppDelegate.Session.DevicePassword)
|
|
|
|
if (decryptedPrivateKey != nil)
|
|
{
|
|
let keyPair = Core.Security.Curve25519.CreateKeyPair(_privateKey: decryptedPrivateKey!, _publicKey: ViewController.Settings!.public_key!)
|
|
|
|
let sharedKey = keyPair.GetSharedKey(peerPublicKeyBase64: self.CurrentDownload!.server_public_key!)
|
|
|
|
if(sharedKey != nil)
|
|
{
|
|
let decrypted_content = Core.Security.AES.Decrypt(value: self.CurrentDownload!.encrypted_content!, deriveKey: sharedKey!)
|
|
|
|
if(decrypted_content != nil)
|
|
{
|
|
let local_encrypted = Core.Security.AES.Encrypt(value: decrypted_content!, password: AppDelegate.Session.DevicePassword)
|
|
|
|
if(local_encrypted != nil)
|
|
{
|
|
let now = Date()
|
|
let dateFormatter = DateFormatter()
|
|
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
|
|
|
|
self.CurrentDownloadResults!.picked_up = true
|
|
self.CurrentDownloadResults!.picked_up_ts = dateFormatter.string(from: now)
|
|
self.CurrentDownloadResults!.file_checksum = Core.Security.SHA512.Encrypt(value: decrypted_content!)
|
|
|
|
if(Core.System.WriteToEncryptedStorage(filename: self.CurrentDownloadResults!.pgs!, data: local_encrypted!.data(using: .utf8)!) &&
|
|
Core.Database.Results.Update(results: self.CurrentDownloadResults!))
|
|
{
|
|
self.loadResults(onlyLocale: true)
|
|
|
|
if(show)
|
|
{
|
|
self.loadPDF(decryptedContent: Data(base64Encoded: decrypted_content!)!)
|
|
}
|
|
|
|
let checksum = Core.Models.Request.CheckFileChecksum()
|
|
checksum.pgs = self.CurrentDownloadResults!.pgs
|
|
checksum.udid = AppDelegate.Session.Device!.udid
|
|
checksum.device_token = AppDelegate.Session.Device!.token!
|
|
checksum.client_public_key = ViewController.Settings!.public_key
|
|
checksum.verificator_hash = ViewController.Settings!.verificator_hash
|
|
checksum.file_checksum = self.CurrentDownloadResults!.file_checksum
|
|
self.sendPickedUp(checksum: checksum)
|
|
self.CurrentDownload = nil
|
|
self.CurrentDownloadResults = nil
|
|
}
|
|
else
|
|
{
|
|
self.PopupPasswordConfirm_HideLoading(message: Core.Lang.Get(key: "ERROR_COULD_NOT_SAVE_ENCRYPTED"))
|
|
Core.Log.Critical(msg: "could not store encrypted downloaded results", namespace: "ViewController", method: "encryptDownload")
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self.PopupPasswordConfirm_HideLoading(message: Core.Lang.Get(key: "ERROR_COULD_NOT_SAVE_ENCRYPTED"))
|
|
Core.Log.Critical(msg: "could not store encrypted downloaded results", namespace: "ViewController", method: "encryptDownload")
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self.PopupPasswordConfirm_HideLoading(message: Core.Lang.Get(key: "ERROR_COULD_NOT_DECRYPT"))
|
|
Core.Log.Critical(msg: "could not decrypt downloaded results", namespace: "ViewController", method: "encryptDownload")
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self.PopupPasswordConfirm_HideLoading(message: Core.Lang.Get(key: "ERROR_COULD_NOT_DECRYPT"))
|
|
Core.Log.Critical(msg: "could not decrypt downloaded results", namespace: "ViewController", method: "encryptDownload")
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self.PopupPasswordConfirm_HideLoading(message: Core.Lang.Get(key: "ERROR_INVALID_PASSWORD"))
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self.PopupPasswordConfirm_HideLoading(message: Core.Lang.Get(key: "ERROR_DOWNLOAD_NOT_FOUND"))
|
|
Core.Log.Critical(msg: "no download found for encryption", namespace: "ViewController", method: "encryptDownload")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Loads encrypted file from the encrypted storage and decrypts it by master password of user
|
|
*/
|
|
private func encryptFile()
|
|
{
|
|
if(self.CurrentDownloadResults != nil)
|
|
{
|
|
let filePath = Core.System.GetURLForStorageEncryptedFile(filename: self.CurrentDownloadResults!.pgs!)
|
|
|
|
if(filePath != nil && Core.System.FileExists(atPath: filePath!.path))
|
|
{
|
|
let encrypted_data = Core.System.ReadFromEncryptedStorage(filename: self.CurrentDownloadResults!.pgs!)
|
|
|
|
if(encrypted_data != nil)
|
|
{
|
|
let encrypted_content = String(data: encrypted_data!, encoding: .utf8)!
|
|
let local_decrypted = Core.Security.AES.Decrypt(value: encrypted_content, password: AppDelegate.Session.DevicePassword)
|
|
|
|
if(local_decrypted != nil)
|
|
{
|
|
self.loadResults()
|
|
self.loadPDF(decryptedContent: Data(base64Encoded: local_decrypted!)!)
|
|
self.CurrentDownload = nil
|
|
self.CurrentDownloadResults = nil
|
|
}
|
|
else
|
|
{
|
|
self.PopupPasswordConfirm_HideLoading(message: Core.Lang.Get(key: "ERROR_INVALID_PASSWORD"))
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self.PopupPasswordConfirm_HideLoading(message: Core.Lang.Get(key: "ERROR_ENCRYPTED_FILE_NOT_FOUND"))
|
|
Core.Log.Critical(msg: "encrypted file not found", namespace: "ViewController", method: "encryptFile")
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self.PopupPasswordConfirm_HideLoading(message: Core.Lang.Get(key: "ERROR_ENCRYPTED_FILE_NOT_FOUND"))
|
|
Core.Log.Critical(msg: "encrypted file not found", namespace: "ViewController", method: "encryptFile")
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self.PopupPasswordConfirm_HideLoading(message: Core.Lang.Get(key: "ERROR_ENCRYPTED_FILE_NOT_FOUND"))
|
|
Core.Log.Critical(msg: "encrypted file not found", namespace: "ViewController", method: "encryptFile")
|
|
}
|
|
}
|
|
|
|
//MARK: Loads PDFViewer with decrypted content
|
|
private func loadPDF(decryptedContent: Data)
|
|
{
|
|
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
|
let pdfViewController = storyboard.instantiateViewController(withIdentifier: "PDFViewController") as! PDFViewController
|
|
pdfViewController.setContent(data: decryptedContent)
|
|
|
|
pdfViewController.modalPresentationStyle = .fullScreen
|
|
let transition = CATransition()
|
|
transition.duration = 0.25
|
|
transition.type = .push
|
|
transition.subtype = .fromRight
|
|
self.view.window!.layer.add(transition, forKey: kCATransition)
|
|
|
|
self.present(pdfViewController, animated: false)
|
|
}
|
|
|
|
@IBAction func PopupPasswordConfirm_BtnCancelClick(_ sender: Any)
|
|
{
|
|
self.hidePasswordConfirm()
|
|
}
|
|
|
|
@IBAction func PopupPasswordConfirm_BtnEncryptClick(_ sender: Any)
|
|
{
|
|
self.processEncryption()
|
|
}
|
|
|
|
/**
|
|
* Encrypts ether already downloaded results from the device or downloads first the results from the server and encrypts thet after downloading
|
|
*/
|
|
|
|
private func processEncryption(show: Bool = true)
|
|
{
|
|
if(self.CurrentDownload != nil)
|
|
{
|
|
self.encryptDownload(show: show)
|
|
}
|
|
else if(self.CurrentDownloadResults != nil)
|
|
{
|
|
self.encryptFile()
|
|
}
|
|
}
|
|
|
|
//MARK: END Download & PDF FUNCTIONS
|
|
|
|
//MARK: BEGIN Bottom Menu
|
|
|
|
@IBAction func BottonMenuOpenerClick(_ sender: Any)
|
|
{
|
|
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
|
let settingsPwdController = storyboard.instantiateViewController(identifier: "SettingsController")
|
|
|
|
settingsPwdController.modalPresentationStyle = .fullScreen
|
|
let transition = CATransition()
|
|
transition.duration = 0.25
|
|
transition.type = .push
|
|
transition.subtype = .fromRight
|
|
self.view.window!.layer.add(transition, forKey: kCATransition)
|
|
self.present(settingsPwdController, animated: false)
|
|
}
|
|
|
|
//MARK: END Bottom Menu
|
|
}
|