diff --git a/DGCAVerifier/Models/Internal/Link.swift b/DGCAVerifier/Models/Internal/Link.swift index e524fbc..94c8721 100644 --- a/DGCAVerifier/Models/Internal/Link.swift +++ b/DGCAVerifier/Models/Internal/Link.swift @@ -33,5 +33,6 @@ enum Link { case whyQrNotValid case qrValidityRange case whichQrScan + case whyVerificationNeeded } diff --git a/DGCAVerifier/Pages/Camera/CameraViewController.swift b/DGCAVerifier/Pages/Camera/CameraViewController.swift index d488d18..f6558f7 100644 --- a/DGCAVerifier/Pages/Camera/CameraViewController.swift +++ b/DGCAVerifier/Pages/Camera/CameraViewController.swift @@ -35,7 +35,7 @@ protocol CameraDelegate { func startOperations() } -let mockQRCode = "" +let mockQRCode = "HC1:6BFOXN%TS3DHPVO13J /G-/2YRVA.Q/R82JD2FCJG96V75DOW%IY17EIHY P8L6IWM$S4U45P84HW6U/4:84LC6 YM::QQHIZC4.OI1RM8ZA.A5:S9MKN4NN3F85QNCY0O%0VZ001HOC9JU0D0HT0HB2PL/IB*09B9LW4T*8+DCMH0LDK2%KI*V AQ2%KYZPQV6YP8722XOE7:8IPC2L4U/6H1D31BLOETI0K/4VMA/.6LOE:/8IL882B+SGK*R3T3+7A.N88J4R$F/MAITHW$P7S3-G9++9-G9+E93ZM$96TV6QRR 1JI7JSTNCA7G6MXYQYYQQKRM64YVQB95326FW4AJOMKMV35U:7-Z7QT499RLHPQ15O+4/Z6E 6U963X7$8Q$HMCP63HU$*GT*Q3-Q4+O7F6E%CN4D74DWZJ$7K+ CZEDB2M$9C1QD7+2K3475J%6VAYCSP0VSUY8WU9SG43A-RALVMO8+-VD2PRPTB7S015SSFW/BE1S1EV*2Q396Q*4TVNAZHJ7N471FPL-CA+2KG-6YPPB7C%40F18N4" class CameraViewController: UIViewController { weak var coordinator: CameraCoordinator? @@ -46,13 +46,20 @@ class CameraViewController: UIViewController { @IBOutlet weak var countryButton: AppButton! @IBOutlet weak var flashButton: AppButton! @IBOutlet weak var switchButton: UIButton! - - private var captureSession = AVCaptureSession() + + private var headerBar: HeaderBar? + private var footerBar: FooterBar? + + private var captureSession = AVCaptureSession() + private var cameraPreviewLayer: AVCaptureVideoPreviewLayer? init(coordinator: CameraCoordinator, country: CountryModel? = nil) { self.coordinator = coordinator self.country = country super.init(nibName: "CameraViewController", bundle: nil) + + self.initializeHeaderBar() + self.initializeFooterBar() } required init?(coder: NSCoder) { @@ -80,6 +87,13 @@ class CameraViewController: UIViewController { super.viewWillAppear(animated) startOperations() } + + override func viewWillLayoutSubviews() { + super.viewWillLayoutSubviews() + DispatchQueue.main.async { + self.cameraPreviewLayer?.frame = self.cameraView.frame + } + } public func startOperations() { setupCamera() @@ -96,6 +110,11 @@ class CameraViewController: UIViewController { Store.set(AVCaptureDevice.isTorchActive, for: .isTorchActive) } + @objc private func flashSwitchAction() { + AVCaptureDevice.switchTorch() + Store.set(AVCaptureDevice.isTorchActive, for: .isTorchActive) + } + @IBAction func backToRoot(_ sender: Any) { coordinator?.dismissToRoot() } @@ -107,6 +126,13 @@ class CameraViewController: UIViewController { setupFlash() } + @objc private func switchCameraAction() { + changeCameraMode() + setupCamera() + startRunning() + setupFlash() + } + private func found(payload: String) { let vc = coordinator?.navigationController.visibleViewController guard !(vc is VerificationViewController) else { return } @@ -120,6 +146,23 @@ class CameraViewController: UIViewController { } coordinator?.validate(payload: payload, country: country, delegate: self) } + + @objc private func goBack() { + coordinator?.dismiss() + } + + private func initializeHeaderBar() { + self.headerBar = HeaderBar() + self.headerBar?.backButton.addTarget(self, action: #selector(goBack), for: .touchUpInside) + self.headerBar?.switchCameraButton.addTarget(self, action: #selector(switchCameraAction), for: .touchUpInside) + self.headerBar?.flashButton.addTarget(self, action: #selector(flashSwitchAction), for: .touchUpInside) + } + + private func initializeFooterBar() { + let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(goBack)) + self.footerBar = FooterBar() + self.footerBar?.closeView.addGestureRecognizer(gestureRecognizer) + } private func initializeBackButton() { backButton.style = .minimal @@ -127,10 +170,10 @@ class CameraViewController: UIViewController { } private func initializeFlashButton() { - flashButton.cornerRadius = 30.0 - flashButton.backgroundColor = .clear - flashButton.setImage(UIImage(named: "flash-camera")) - flashButton.isHidden = Store.getBool(key: .isFrontCameraActive) + self.headerBar?.flashButton.cornerRadius = 30.0 + self.headerBar?.flashButton.backgroundColor = .clear + self.headerBar?.flashButton.setImage(UIImage(named: "flash-camera")) + self.headerBar?.flashButton.isHidden = Store.getBool(key: .isFrontCameraActive) } private func initializeCountryButton() { @@ -147,14 +190,14 @@ class CameraViewController: UIViewController { private func changeCameraMode() { let frontCameraActive = Store.getBool(key: .isFrontCameraActive) Store.set(!frontCameraActive, for: .isFrontCameraActive) - flashButton.isHidden = !frontCameraActive + self.headerBar?.flashButton.isHidden = !frontCameraActive } private func setupCamera() { cleanSession() captureSession.setup(self, with: currentCameraMode) - let layer = captureSession.getPreviewLayer(for: view) - cameraView.layer.insertSublayer(layer, at: 0) + cameraPreviewLayer = captureSession.getPreviewLayer(for: cameraView) + cameraView.layer.insertSublayer(cameraPreviewLayer!, at: 0) } private func cleanSession() { @@ -195,6 +238,20 @@ class CameraViewController: UIViewController { } } +extension CameraViewController: HeaderFooterDelegate { + public var header: UIView? { + return self.headerBar + } + + public var contentVC: UIViewController? { + return self + } + + public var footer: UIView? { + return self.footerBar + } +} + extension CameraViewController: CameraDelegate { func startRunning() { diff --git a/DGCAVerifier/Pages/Camera/CameraViewController.xib b/DGCAVerifier/Pages/Camera/CameraViewController.xib index 40be7c4..ec51a72 100644 --- a/DGCAVerifier/Pages/Camera/CameraViewController.xib +++ b/DGCAVerifier/Pages/Camera/CameraViewController.xib @@ -1,9 +1,9 @@ - + - + @@ -24,14 +24,14 @@ - - + + - + - - + @@ -242,7 +242,6 @@ - @@ -250,10 +249,16 @@ + + + + + + diff --git a/DGCAVerifier/Pages/Home/HomeViewController.swift b/DGCAVerifier/Pages/Home/HomeViewController.swift index 9fd095c..c5137bf 100644 --- a/DGCAVerifier/Pages/Home/HomeViewController.swift +++ b/DGCAVerifier/Pages/Home/HomeViewController.swift @@ -24,6 +24,7 @@ import UIKit import RealmSwift +import SwiftyJSON typealias Tap = UITapGestureRecognizer @@ -47,6 +48,8 @@ class HomeViewController: UIViewController { @IBOutlet weak var countriesButton: AppButton! @IBOutlet weak var updateNowButton: AppButton! @IBOutlet weak var debugInfoButton: UIButton! + @IBOutlet weak var titleLabel: AppLabel! + @IBOutlet weak var infoButton: UIButton! @IBOutlet weak var lastFetchContainer: UIView! @IBOutlet weak var progressContainer: UIView! @@ -86,15 +89,22 @@ class HomeViewController: UIViewController { setScanModeButtonText() } + override func viewWillLayoutSubviews() { + super.viewWillLayoutSubviews() + view.reloadInputViews() + } + private func initialize() { bindScanEnabled() setUpSettingsAction() + setHomeTitle() setFAQ() setPrivacyPolicy() setVersion() setScanModeButton() setScanButton() setCountriesButton() + setInfoButton() setDebugView() updateLastFetch(isLoading: viewModel.isLoading.value ?? false) updateNowButton.contentHorizontalAlignment = .center @@ -172,6 +182,17 @@ class HomeViewController: UIViewController { } } + private func setHomeTitle(){ + let localizedBaseHomeTitle = "home.title".localized + let boldLocalizedText = "home.title.bold".localized + let homeTitle: NSMutableAttributedString = .init(string: localizedBaseHomeTitle, attributes: nil) + let boldRange: NSRange = (homeTitle.string as NSString).range(of: boldLocalizedText) + homeTitle.setAttributes([NSAttributedString.Key.font: UIFont(name: "TitilliumWeb-Bold", size: 30)!], range: boldRange) + titleLabel.attributedText = homeTitle + titleLabel.adjustsFontSizeToFitWidth = true + titleLabel.minimumScaleFactor = 0.2 + } + private func setFAQ() { let title = Link.faq.title.localized let tap = Tap(target: self, action: #selector(faqDidTap)) @@ -194,6 +215,14 @@ class HomeViewController: UIViewController { setScanModeButtonText() } + @objc func showInfoAlert(){ + showCustomAlert(key: "scan.mode.info", isHTMLBased: true) + } + + private func setInfoButton() { + infoButton.addTarget(self, action: #selector(showInfoAlert), for: .touchUpInside) + } + private func setScanModeButtonStyle() { scanModeButton.style = .clear scanModeButton.setRightImage(named: "icon_arrow-right") @@ -334,14 +363,15 @@ class HomeViewController: UIViewController { self.present(alertController, animated: true, completion: nil) } - private func showCustomAlert(key: String) { + private func showCustomAlert(key: String, isHTMLBased: Bool = false) { AppAlertViewController.present(for: self, with: .init( title: "alert.\(key).title".localized, message: "alert.\(key).message".localized, confirmAction: {}, confirmActionTitle: "alert.default.action".localized, cancelAction: {}, - cancelActionTitle: nil)) + cancelActionTitle: nil, + isHTMLBased: isHTMLBased)) } private func disableScanButton(){ @@ -369,7 +399,7 @@ class HomeViewController: UIViewController { let isCRLDownloadCompleted = CRLDataStorage.shared.isCRLDownloadCompleted let isCRLAllowed = CRLSynchronizationManager.shared.isSyncEnabled - guard Store.getBool(key: .isScanModeSet) else { return showCustomAlert(key: "scan.unset") } + guard Store.getBool(key: .isScanModeSet) else { return showCustomAlert(key: "scan.unset", isHTMLBased: true) } guard certFetchUpdated else { showCustomAlert(key: "no.keys") diff --git a/DGCAVerifier/Pages/Home/HomeViewController.xib b/DGCAVerifier/Pages/Home/HomeViewController.xib index dbb76c1..ee1e230 100644 --- a/DGCAVerifier/Pages/Home/HomeViewController.xib +++ b/DGCAVerifier/Pages/Home/HomeViewController.xib @@ -1,9 +1,9 @@ - + - + @@ -14,6 +14,7 @@ + @@ -22,6 +23,7 @@ + @@ -67,7 +69,7 @@ - - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DGCAVerifier/Utils/ModelExtensions/Link+Values.swift b/DGCAVerifier/Utils/ModelExtensions/Link+Values.swift index bc9f1d8..69e2e81 100644 --- a/DGCAVerifier/Utils/ModelExtensions/Link+Values.swift +++ b/DGCAVerifier/Utils/ModelExtensions/Link+Values.swift @@ -25,37 +25,40 @@ import Foundation -private let PRIVACY_POLICIES = "https://www.dgc.gov.it/web/pn.html" -private let FAQ = "https://www.dgc.gov.it/web/faq.html#verifica19" -private let HOW_TO = "https://www.dgc.gov.it/web/faq.html#verifica19" -private let WHY_NOT_VALID = "https://www.dgc.gov.it/web/faq.html#verifica19" -private let VALIDITY_RANGE = "https://www.dgc.gov.it/web/faq.html#verifica19" -private let WHICH_QR = "https://www.dgc.gov.it/web/faq.html#verifica19" -private let STORE = "itms-apps://apple.com/app/id1565800117" +private let PRIVACY_POLICIES = "https://www.dgc.gov.it/web/pn.html" +private let FAQ = "https://www.dgc.gov.it/web/app.html" +private let HOW_TO = "https://www.dgc.gov.it/web/faq.html#verifica19" +private let WHY_NOT_VALID = "https://www.dgc.gov.it/web/faq.html#verifica19" +private let VALIDITY_RANGE = "https://www.dgc.gov.it/web/faq.html#verifica19" +private let WHICH_QR = "https://www.dgc.gov.it/web/faq.html#verifica19" +private let STORE = "itms-apps://apple.com/app/id1565800117" +private let WHY_VERIFICATION_NEEDED = "https://www.dgc.gov.it/web/faq.html#verifica19" extension Link { var url: String { switch self { - case .faq: return FAQ - case .privacyPolicy: return PRIVACY_POLICIES - case .store: return STORE - case .whatCanBeDone: return HOW_TO - case .whyQrNotValid: return WHY_NOT_VALID - case .qrValidityRange: return VALIDITY_RANGE - case .whichQrScan: return WHICH_QR + case .faq: return FAQ + case .privacyPolicy: return PRIVACY_POLICIES + case .store: return STORE + case .whatCanBeDone: return HOW_TO + case .whyQrNotValid: return WHY_NOT_VALID + case .qrValidityRange: return VALIDITY_RANGE + case .whichQrScan: return WHICH_QR + case .whyVerificationNeeded: return WHY_VERIFICATION_NEEDED } } var title: String { switch self { - case .faq: return "links.read.faq" - case .privacyPolicy: return "links.read.privacy.policy" - case .store: return "link.go.to.store" - case .whatCanBeDone: return "links.what.can.be.done" - case .whyQrNotValid: return "links.why.qr.code.not.valid" - case .qrValidityRange: return "links.qr.code.validity.range" - case .whichQrScan: return "links.which.qr.code.scan" + case .faq: return "links.read.faq" + case .privacyPolicy: return "links.read.privacy.policy" + case .store: return "link.go.to.store" + case .whatCanBeDone: return "links.what.can.be.done" + case .whyQrNotValid: return "links.why.qr.code.not.valid" + case .qrValidityRange: return "links.qr.code.validity.range" + case .whichQrScan: return "links.which.qr.code.scan" + case .whyVerificationNeeded: return "links.why.qr.code.verification.needed" } } diff --git a/DGCAVerifier/Utils/ModelExtensions/Status+Configuration.swift b/DGCAVerifier/Utils/ModelExtensions/Status+Configuration.swift index fcedf9d..ebe08b0 100644 --- a/DGCAVerifier/Utils/ModelExtensions/Status+Configuration.swift +++ b/DGCAVerifier/Utils/ModelExtensions/Status+Configuration.swift @@ -113,7 +113,7 @@ extension Status { case .notValid: return [.whyQrNotValid] case .expired: return [.whyQrNotValid] case .notGreenPass: return [.whichQrScan] - case .verificationIsNeeded: return [.whyQrNotValid] + case .verificationIsNeeded: return [.whyVerificationNeeded] case .revokedGreenPass: return [] } } diff --git a/DGCAVerifier/Utils/UIExtensions/UIView/UIView+EmbedSubview.swift b/DGCAVerifier/Utils/UIExtensions/UIView/UIView+EmbedSubview.swift new file mode 100644 index 0000000..dfa1a98 --- /dev/null +++ b/DGCAVerifier/Utils/UIExtensions/UIView/UIView+EmbedSubview.swift @@ -0,0 +1,19 @@ +// +// UIView+EmbedSubview.swift +// Verifier +// +// Created by Johnny Bueti on 08/02/22. +// + +import Foundation +import UIKit + +extension UIView { + public func embedSubview(subview: UIView) { + let constraints = self.getAnchorConstraintsRelativeTo(view: subview) + subview.translatesAutoresizingMaskIntoConstraints = false + + self.addSubview(subview) + NSLayoutConstraint.activate(constraints) + } +} diff --git a/DGCAVerifier/Utils/UIExtensions/UIView/UIView+NSLayoutConstraint.swift b/DGCAVerifier/Utils/UIExtensions/UIView/UIView+NSLayoutConstraint.swift new file mode 100644 index 0000000..60fef32 --- /dev/null +++ b/DGCAVerifier/Utils/UIExtensions/UIView/UIView+NSLayoutConstraint.swift @@ -0,0 +1,20 @@ +// +// UIView+NSLayoutConstraint.swift +// Verifier +// +// Created by Johnny Bueti on 08/02/22. +// + +import Foundation +import UIKit + +extension UIView { + public func getAnchorConstraintsRelativeTo(view: UIView) -> [NSLayoutConstraint] { + return [ + self.leadingAnchor.constraint(equalTo: view.leadingAnchor), + self.trailingAnchor.constraint(equalTo: view.trailingAnchor), + self.topAnchor.constraint(equalTo: view.topAnchor), + self.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ] + } +} diff --git a/Verifier.xcodeproj/project.pbxproj b/Verifier.xcodeproj/project.pbxproj index de16f98..fbf802f 100644 --- a/Verifier.xcodeproj/project.pbxproj +++ b/Verifier.xcodeproj/project.pbxproj @@ -7,6 +7,18 @@ objects = { /* Begin PBXBuildFile section */ + 140B09CD27B2CB4C003A017F /* UIView+NSLayoutConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 140B09CC27B2CB4C003A017F /* UIView+NSLayoutConstraint.swift */; }; + 140B09CE27B2CB4C003A017F /* UIView+NSLayoutConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 140B09CC27B2CB4C003A017F /* UIView+NSLayoutConstraint.swift */; }; + 140B09D027B2CF24003A017F /* UIView+EmbedSubview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 140B09CF27B2CF24003A017F /* UIView+EmbedSubview.swift */; }; + 140B09D127B2CF24003A017F /* UIView+EmbedSubview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 140B09CF27B2CF24003A017F /* UIView+EmbedSubview.swift */; }; + 140B09D327B2D16F003A017F /* HeaderBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = 140B09D227B2D16F003A017F /* HeaderBar.xib */; }; + 140B09D427B2D16F003A017F /* HeaderBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = 140B09D227B2D16F003A017F /* HeaderBar.xib */; }; + 140B09D727B2D1B2003A017F /* HeaderBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 140B09D627B2D1B2003A017F /* HeaderBar.swift */; }; + 140B09D827B2D1B2003A017F /* HeaderBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 140B09D627B2D1B2003A017F /* HeaderBar.swift */; }; + 140B09E027B41C69003A017F /* FooterBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 140B09DF27B41C69003A017F /* FooterBar.swift */; }; + 140B09E127B41C69003A017F /* FooterBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 140B09DF27B41C69003A017F /* FooterBar.swift */; }; + 140B09E327B41C91003A017F /* FooterBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = 140B09E227B41C91003A017F /* FooterBar.xib */; }; + 140B09E427B41C91003A017F /* FooterBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = 140B09E227B41C91003A017F /* FooterBar.xib */; }; 1410B20B271DBADD00F912BA /* PickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1410B20A271DBADD00F912BA /* PickerViewController.swift */; }; 1410B20D271EAE6000F912BA /* PickerViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1410B20C271EAE6000F912BA /* PickerViewController.xib */; }; 145CC08B27B5155B00F2D01F /* CasiDiTest.csv in Resources */ = {isa = PBXBuildFile; fileRef = 145CC08A27B5155B00F2D01F /* CasiDiTest.csv */; }; @@ -16,6 +28,12 @@ 149FF578273D6F7D00DFC035 /* RevocationValidityCheckTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 149FF575273D6F7400DFC035 /* RevocationValidityCheckTests.swift */; }; 149FF57D2745143C00DFC035 /* PickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1410B20A271DBADD00F912BA /* PickerViewController.swift */; }; 149FF57E2745144300DFC035 /* PickerViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1410B20C271EAE6000F912BA /* PickerViewController.xib */; }; + 14B94A5727BFB40700B2B906 /* ExtendedUIButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14B94A5627BFB40700B2B906 /* ExtendedUIButton.swift */; }; + 14B94A5827BFB40700B2B906 /* ExtendedUIButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14B94A5627BFB40700B2B906 /* ExtendedUIButton.swift */; }; + 14CD25E127B2BA6B007DF2A4 /* HFBackViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14CD25DF27B2BA6B007DF2A4 /* HFBackViewController.swift */; }; + 14CD25E227B2BA6B007DF2A4 /* HFBackViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14CD25DF27B2BA6B007DF2A4 /* HFBackViewController.swift */; }; + 14CD25E327B2BA6B007DF2A4 /* HFBackViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 14CD25E027B2BA6B007DF2A4 /* HFBackViewController.xib */; }; + 14CD25E427B2BA6B007DF2A4 /* HFBackViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 14CD25E027B2BA6B007DF2A4 /* HFBackViewController.xib */; }; 14D4F19627B575E7002B2F00 /* mockedSettings.json in Resources */ = {isa = PBXBuildFile; fileRef = 14D4F19527B57458002B2F00 /* mockedSettings.json */; }; 14D4F19727B575E8002B2F00 /* mockedSettings.json in Resources */ = {isa = PBXBuildFile; fileRef = 14D4F19527B57458002B2F00 /* mockedSettings.json */; }; 14D4F19827B575E8002B2F00 /* mockedSettings.json in Resources */ = {isa = PBXBuildFile; fileRef = 14D4F19527B57458002B2F00 /* mockedSettings.json */; }; @@ -391,11 +409,20 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 140B09CC27B2CB4C003A017F /* UIView+NSLayoutConstraint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+NSLayoutConstraint.swift"; sourceTree = ""; }; + 140B09CF27B2CF24003A017F /* UIView+EmbedSubview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+EmbedSubview.swift"; sourceTree = ""; }; + 140B09D227B2D16F003A017F /* HeaderBar.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HeaderBar.xib; sourceTree = ""; }; + 140B09D627B2D1B2003A017F /* HeaderBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeaderBar.swift; sourceTree = ""; }; + 140B09DF27B41C69003A017F /* FooterBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FooterBar.swift; sourceTree = ""; }; + 140B09E227B41C91003A017F /* FooterBar.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FooterBar.xib; sourceTree = ""; }; 1410B20A271DBADD00F912BA /* PickerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickerViewController.swift; sourceTree = ""; }; 1410B20C271EAE6000F912BA /* PickerViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PickerViewController.xib; sourceTree = ""; }; 145CC08A27B5155B00F2D01F /* CasiDiTest.csv */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CasiDiTest.csv; sourceTree = ""; }; 1462330727A3EA580073A323 /* HCertGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HCertGenerator.swift; sourceTree = ""; }; 149FF575273D6F7400DFC035 /* RevocationValidityCheckTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RevocationValidityCheckTests.swift; sourceTree = ""; }; + 14B94A5627BFB40700B2B906 /* ExtendedUIButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtendedUIButton.swift; sourceTree = ""; }; + 14CD25DF27B2BA6B007DF2A4 /* HFBackViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HFBackViewController.swift; sourceTree = ""; }; + 14CD25E027B2BA6B007DF2A4 /* HFBackViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HFBackViewController.xib; sourceTree = ""; }; 14D4F19527B57458002B2F00 /* mockedSettings.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = mockedSettings.json; sourceTree = ""; }; 14EB4294275FAE8A006E9183 /* DebugView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DebugView.xib; sourceTree = ""; }; 14EB4296275FAE9F006E9183 /* DebugViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugViewController.swift; sourceTree = ""; }; @@ -632,6 +659,24 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 140B09D527B2D1A1003A017F /* HeaderBar */ = { + isa = PBXGroup; + children = ( + 140B09D227B2D16F003A017F /* HeaderBar.xib */, + 140B09D627B2D1B2003A017F /* HeaderBar.swift */, + ); + path = HeaderBar; + sourceTree = ""; + }; + 140B09DB27B41BF9003A017F /* FooterBar */ = { + isa = PBXGroup; + children = ( + 140B09DF27B41C69003A017F /* FooterBar.swift */, + 140B09E227B41C91003A017F /* FooterBar.xib */, + ); + path = FooterBar; + sourceTree = ""; + }; 1410B209271DBACD00F912BA /* PickerVC */ = { isa = PBXGroup; children = ( @@ -641,6 +686,15 @@ path = PickerVC; sourceTree = ""; }; + 14CD25DE27B2B9E1007DF2A4 /* HeaderFooterBackViewController */ = { + isa = PBXGroup; + children = ( + 14CD25DF27B2BA6B007DF2A4 /* HFBackViewController.swift */, + 14CD25E027B2BA6B007DF2A4 /* HFBackViewController.xib */, + ); + path = HeaderFooterBackViewController; + sourceTree = ""; + }; 14EB4293275FAE6A006E9183 /* Debug */ = { isa = PBXGroup; children = ( @@ -713,6 +767,7 @@ 65021B5A26AED0A1004C3D14 /* AppLabelUrl.swift */, 65E7000B26AF753C00715CCC /* AppView.swift */, 659605E026E763D2008AD4E2 /* AppAlert */, + 14B94A5627BFB40700B2B906 /* ExtendedUIButton.swift */, ); path = BaseComponents; sourceTree = ""; @@ -764,6 +819,8 @@ 65C3A55626AEF8F3000BBCC5 /* UIView+Borders.swift */, 65E7000026AF6E1F00715CCC /* UIStackView+ArrangedSubViews.swift */, 90CDC6D8271F049A00707836 /* UIView+NibFile.swift */, + 140B09CC27B2CB4C003A017F /* UIView+NSLayoutConstraint.swift */, + 140B09CF27B2CF24003A017F /* UIView+EmbedSubview.swift */, ); path = UIView; sourceTree = ""; @@ -1041,6 +1098,8 @@ 65E7000726AF71AC00715CCC /* CustomViews */ = { isa = PBXGroup; children = ( + 140B09DB27B41BF9003A017F /* FooterBar */, + 140B09D527B2D1A1003A017F /* HeaderBar */, 65021B4426AEC6AE004C3D14 /* AppShadowView */, 65E7001126AF7BA300715CCC /* FaqView */, 659605F126E790EE008AD4E2 /* ProgressView */, @@ -1145,6 +1204,7 @@ 9020C5F12721C1FB00F45CA7 /* CustomControllers */ = { isa = PBXGroup; children = ( + 14CD25DE27B2B9E1007DF2A4 /* HeaderFooterBackViewController */, 1410B209271DBACD00F912BA /* PickerVC */, ); path = CustomControllers; @@ -1478,6 +1538,7 @@ 9020C5E82721601E00F45CA7 /* CountryCell.xib in Resources */, 14EB42A1275FE2B3006E9183 /* DebugCell.xib in Resources */, 149FF57E2745144300DFC035 /* PickerViewController.xib in Resources */, + 140B09E427B41C91003A017F /* FooterBar.xib in Resources */, 65E281DF2697259D00377913 /* TitilliumWeb-SemiBoldItalic.ttf in Resources */, 65E281E02697259D00377913 /* Roboto-ThinItalic.ttf in Resources */, 65E281E12697259D00377913 /* Roboto-LightItalic.ttf in Resources */, @@ -1486,6 +1547,8 @@ 65E281E42697259D00377913 /* VerificationViewController.xib in Resources */, 14EB429A275FAFFF006E9183 /* DebugView.xib in Resources */, 65E281E52697259D00377913 /* Roboto-Italic.ttf in Resources */, + 14CD25E427B2BA6B007DF2A4 /* HFBackViewController.xib in Resources */, + 140B09D427B2D16F003A017F /* HeaderBar.xib in Resources */, 65E281E62697259D00377913 /* Roboto-MediumItalic.ttf in Resources */, 65E281E72697259D00377913 /* TitilliumWeb-Regular.ttf in Resources */, 65E281E82697259D00377913 /* Roboto-Light.ttf in Resources */, @@ -1532,6 +1595,9 @@ 9F90C59B265E591E00B2F992 /* TitilliumWeb-ExtraLight.ttf in Resources */, 9F90C5A9265E591E00B2F992 /* Roboto-Black.ttf in Resources */, 65E2816A2697217B00377913 /* VerificationViewController.xib in Resources */, + 14CD25E327B2BA6B007DF2A4 /* HFBackViewController.xib in Resources */, + 140B09D327B2D16F003A017F /* HeaderBar.xib in Resources */, + 140B09E327B41C91003A017F /* FooterBar.xib in Resources */, 659605F626E7927C008AD4E2 /* ProgressView.xib in Resources */, 9F90C5A4265E591E00B2F992 /* Roboto-Italic.ttf in Resources */, 9F90C599265E591E00B2F992 /* Roboto-MediumItalic.ttf in Resources */, @@ -1641,11 +1707,13 @@ 9020C5E62721600D00F45CA7 /* UITableView+Nib.swift in Sources */, 9020C5E72721600D00F45CA7 /* CountryCell.swift in Sources */, 65021B4C26AEC889004C3D14 /* AppButton.swift in Sources */, + 140B09D127B2CF24003A017F /* UIView+EmbedSubview.swift in Sources */, 65E281B92697259D00377913 /* TestValidityCheck.swift in Sources */, 65E281BB2697259D00377913 /* HCert+PersonalData.swift in Sources */, 65E3C1DE2716E444004B2E98 /* AVCaptureDevice+Camera.swift in Sources */, 90C421D0272AFFCE00B50ABC /* Int+String.swift in Sources */, 90C421D1272AFFCE00B50ABC /* Double+Bytes.swift in Sources */, + 140B09CE27B2CB4C003A017F /* UIView+NSLayoutConstraint.swift in Sources */, 656433B526D787C300A41590 /* RevokedDCC.swift in Sources */, 98DCD73F278C853200D4B418 /* HCert+Type.swift in Sources */, 98BF53CA27A94CD800B8FB1A /* UnknownValidators.swift in Sources */, @@ -1694,6 +1762,7 @@ 65021B5326AEC88E004C3D14 /* UIView+Set.swift in Sources */, 6B797DDB26D0528200EB2873 /* String+SHA256.swift in Sources */, 90BED819276A570E006225CE /* String+Link.swift in Sources */, + 14B94A5827BFB40700B2B906 /* ExtendedUIButton.swift in Sources */, 656150E12726A9C40076BAE4 /* String+Bool.swift in Sources */, 658CB71F26AF359100B90EC0 /* UIImage+Rotate.swift in Sources */, 98BF53C027A94BFB00B8FB1A /* RecoveryValidators.swift in Sources */, @@ -1722,6 +1791,8 @@ 65EFB63426B183CF0081682B /* Link+Values.swift in Sources */, 90BD8F50272C1C8A00BE816B /* Constants.swift in Sources */, 65C3A55826AEF8F3000BBCC5 /* UIView+Borders.swift in Sources */, + 14CD25E227B2BA6B007DF2A4 /* HFBackViewController.swift in Sources */, + 140B09E127B41C69003A017F /* FooterBar.swift in Sources */, 65E281CD2697259D00377913 /* Setting.swift in Sources */, 65C3A55526AEF642000BBCC5 /* String+UIImage.swift in Sources */, 6559D94F27199A3300E0E30D /* VNBarcodeObservation+Values.swift in Sources */, @@ -1759,6 +1830,7 @@ 98BF53BA27A9471700B8FB1A /* DGCValidator.swift in Sources */, 65EFB62A26B0BFC00081682B /* CertLogicValidator.swift in Sources */, 65021B5C26AED0A1004C3D14 /* AppLabelUrl.swift in Sources */, + 140B09D827B2D1B2003A017F /* HeaderBar.swift in Sources */, 9037A0AA270EFD490067DCF8 /* SettingsViewModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1799,8 +1871,10 @@ 659605DE26E761D0008AD4E2 /* AppAlertViewController.swift in Sources */, 65EFB60C26B06AD80081682B /* SettingsDataStorage.swift in Sources */, 65021B4A26AEC7C0004C3D14 /* CALayer+Shadow.swift in Sources */, + 14B94A5727BFB40700B2B906 /* ExtendedUIButton.swift in Sources */, 658CB71B26AF27D200B90EC0 /* UIBarButtonItem+Appearance.swift in Sources */, 65E281662697217B00377913 /* HomeViewModel.swift in Sources */, + 140B09CD27B2CB4C003A017F /* UIView+NSLayoutConstraint.swift in Sources */, 65021B3B26AEB291004C3D14 /* ButtonStyle.swift in Sources */, 65E2819C269721ED00377913 /* Date+String.swift in Sources */, 6559D947271996F300E0E30D /* VNBarcodeObservation+Allowed.swift in Sources */, @@ -1828,6 +1902,7 @@ 65EFB5EE26B04D850081682B /* GatewayConnection+Certificates.swift in Sources */, 65E3C1D92716E05D004B2E98 /* AVCaptureDevice+Torch.swift in Sources */, 65E281A7269721ED00377913 /* HCert+Test.swift in Sources */, + 140B09D727B2D1B2003A017F /* HeaderBar.swift in Sources */, 65021B6226AEDCF3004C3D14 /* Palette.swift in Sources */, 658CB72526AF3C1200B90EC0 /* Status+Configuration.swift in Sources */, 65E2816C2697217B00377913 /* ResultView.swift in Sources */, @@ -1840,8 +1915,10 @@ 98BF53BC27A94BD300B8FB1A /* VaccineValidators.swift in Sources */, 98BF53C927A94CD800B8FB1A /* UnknownValidators.swift in Sources */, 65E2816B2697217B00377913 /* VerificationViewModel.swift in Sources */, + 14CD25E127B2BA6B007DF2A4 /* HFBackViewController.swift in Sources */, 65021B5926AECF59004C3D14 /* UIImageView+Inspectable.swift in Sources */, 65E281A2269721ED00377913 /* Cache.swift in Sources */, + 140B09E027B41C69003A017F /* FooterBar.swift in Sources */, 65E281702697217B00377913 /* CameraViewController.swift in Sources */, 90C421CC2729A60900B50ABC /* Int+Bytes.swift in Sources */, 65E7001326AF7BB000715CCC /* FaqView.swift in Sources */, @@ -1865,6 +1942,7 @@ 90BED815276A4F15006225CE /* String+HTML.swift in Sources */, 65EFB62926B0BFC00081682B /* CertLogicValidator.swift in Sources */, 98BF53E127AC3AE900B8FB1A /* ScanMode+UI.swift in Sources */, + 140B09D027B2CF24003A017F /* UIView+EmbedSubview.swift in Sources */, 90A3E616273C6B2C00D161BD /* Array+Utils.swift in Sources */, 659605F926E7A6E0008AD4E2 /* CRLProgress.swift in Sources */, 65021B6826AEEC48004C3D14 /* UIImage+Colors.swift in Sources */, @@ -1962,7 +2040,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.5; + MARKETING_VERSION = 1.2.6; PRODUCT_BUNDLE_IDENTIFIER = it.ministerodellasalute.VerificaC19; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1986,7 +2064,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.5; + MARKETING_VERSION = 1.2.6; PRODUCT_BUNDLE_IDENTIFIER = it.ministerodellasalute.VerificaC19; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2073,7 +2151,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.5; + MARKETING_VERSION = 1.2.6; PRODUCT_BUNDLE_IDENTIFIER = it.ministerodellasalute.VerificaC19; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2098,7 +2176,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.5; + MARKETING_VERSION = 1.2.6; PRODUCT_BUNDLE_IDENTIFIER = it.ministerodellasalute.VerificaC19; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2229,7 +2307,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.5; + MARKETING_VERSION = 1.2.6; PRODUCT_BUNDLE_IDENTIFIER = it.ministerodellasalute.VerificaC19; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2254,7 +2332,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.5; + MARKETING_VERSION = 1.2.6; PRODUCT_BUNDLE_IDENTIFIER = it.ministerodellasalute.VerificaC19; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2448,7 +2526,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.5; + MARKETING_VERSION = 1.2.6; PRODUCT_BUNDLE_IDENTIFIER = it.ministerodellasalute.VerificaC19; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2473,7 +2551,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.5; + MARKETING_VERSION = 1.2.6; PRODUCT_BUNDLE_IDENTIFIER = it.ministerodellasalute.VerificaC19; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "";