diff --git a/MiniScanner.xcodeproj/project.pbxproj b/MiniScanner.xcodeproj/project.pbxproj index ae34c31d48d136a5976feb2b60b388e69feaa8bb..4d01f9a6e0f4e99587312c6bed5d496b46244425 100644 --- a/MiniScanner.xcodeproj/project.pbxproj +++ b/MiniScanner.xcodeproj/project.pbxproj @@ -252,6 +252,10 @@ 6794328C2C689E9F002E5F8D /* WXCompress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6794328B2C689E9F002E5F8D /* WXCompress.swift */; }; 6794328F2C68A991002E5F8D /* mozjpeg in Frameworks */ = {isa = PBXBuildFile; productRef = 6794328E2C68A991002E5F8D /* mozjpeg */; }; 67959CC42C566B7A00CAB102 /* Icons.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 67959CC32C566B7A00CAB102 /* Icons.xcassets */; }; + 679650572C6DE688001C4353 /* SignatureViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 679650552C6DE688001C4353 /* SignatureViewController.swift */; }; + 679650582C6DE688001C4353 /* SignatureViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 679650562C6DE688001C4353 /* SignatureViewController.xib */; }; + 6796505C2C6DE8ED001C4353 /* DefaultSignatureSheetViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6796505A2C6DE8ED001C4353 /* DefaultSignatureSheetViewController.swift */; }; + 6796505D2C6DE8ED001C4353 /* DefaultSignatureSheetViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6796505B2C6DE8ED001C4353 /* DefaultSignatureSheetViewController.xib */; }; 67A20DDD2C57A142009D2F25 /* DocumentLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A20DDC2C57A142009D2F25 /* DocumentLayout.swift */; }; 67A20DE12C57BC56009D2F25 /* DocumentsCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A20DDF2C57BC56009D2F25 /* DocumentsCollectionViewCell.swift */; }; 67A20DE22C57BC56009D2F25 /* DocumentsCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 67A20DE02C57BC56009D2F25 /* DocumentsCollectionViewCell.xib */; }; @@ -576,6 +580,10 @@ 678BD71E2C4D07B100833DA5 /* Image+Images.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Image+Images.swift"; sourceTree = "<group>"; }; 6794328B2C689E9F002E5F8D /* WXCompress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WXCompress.swift; sourceTree = "<group>"; }; 67959CC32C566B7A00CAB102 /* Icons.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Icons.xcassets; sourceTree = "<group>"; }; + 679650552C6DE688001C4353 /* SignatureViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignatureViewController.swift; sourceTree = "<group>"; }; + 679650562C6DE688001C4353 /* SignatureViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SignatureViewController.xib; sourceTree = "<group>"; }; + 6796505A2C6DE8ED001C4353 /* DefaultSignatureSheetViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultSignatureSheetViewController.swift; sourceTree = "<group>"; }; + 6796505B2C6DE8ED001C4353 /* DefaultSignatureSheetViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DefaultSignatureSheetViewController.xib; sourceTree = "<group>"; }; 67A20DDC2C57A142009D2F25 /* DocumentLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentLayout.swift; sourceTree = "<group>"; }; 67A20DDF2C57BC56009D2F25 /* DocumentsCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentsCollectionViewCell.swift; sourceTree = "<group>"; }; 67A20DE02C57BC56009D2F25 /* DocumentsCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DocumentsCollectionViewCell.xib; sourceTree = "<group>"; }; @@ -1631,6 +1639,25 @@ path = Compress; sourceTree = "<group>"; }; + 679650542C6DE5CE001C4353 /* SignatureViewController */ = { + isa = PBXGroup; + children = ( + 679650592C6DE8BD001C4353 /* DefaultSignatureSheetViewController */, + 679650552C6DE688001C4353 /* SignatureViewController.swift */, + 679650562C6DE688001C4353 /* SignatureViewController.xib */, + ); + path = SignatureViewController; + sourceTree = "<group>"; + }; + 679650592C6DE8BD001C4353 /* DefaultSignatureSheetViewController */ = { + isa = PBXGroup; + children = ( + 6796505A2C6DE8ED001C4353 /* DefaultSignatureSheetViewController.swift */, + 6796505B2C6DE8ED001C4353 /* DefaultSignatureSheetViewController.xib */, + ); + path = DefaultSignatureSheetViewController; + sourceTree = "<group>"; + }; 67A20DDE2C57BC32009D2F25 /* DocumentsCollectionViewCell */ = { isa = PBXGroup; children = ( @@ -1789,6 +1816,7 @@ EC8A9B2D254DE96300F9AF99 /* Modules */ = { isa = PBXGroup; children = ( + 679650542C6DE5CE001C4353 /* SignatureViewController */, 539996312C26D40100671340 /* OCRViewController */, 53BAE0EA2C15E0770072189E /* EditViewController */, ECE9BBB2254E331700D45E43 /* Walktrough */, @@ -1923,12 +1951,14 @@ 53014FB32C11A8E80071CE39 /* flash@3x.png in Resources */, 672C46442C47B1F300497EF0 /* Localizable.xcstrings in Resources */, 539EF14E2C2AA43B0041AE1F /* ara.traineddata in Resources */, + 6796505D2C6DE8ED001C4353 /* DefaultSignatureSheetViewController.xib in Resources */, 676C30852C6CDDAE00C29A43 /* IBMPlexSansArabic-Light.ttf in Resources */, 539996352C26D41300671340 /* OCRViewController.xib in Resources */, 53014FB22C11A8E80071CE39 /* flashUnavailable@3x.png in Resources */, 676C30862C6CDDAE00C29A43 /* IBMPlexSansArabic-Bold.ttf in Resources */, 53BAE0EE2C15E0890072189E /* EditViewController.xib in Resources */, 53014FAF2C11A8E80071CE39 /* flash@2x.png in Resources */, + 679650582C6DE688001C4353 /* SignatureViewController.xib in Resources */, 53BEB1482C2968F8005A3567 /* FolderSelectCollectionViewCell.xib in Resources */, 53014FB12C11A8E80071CE39 /* flashUnavailable.png in Resources */, 67D714B52C5161A30065E6F4 /* Images.xcassets in Resources */, @@ -2125,6 +2155,7 @@ 67106C942C4EAC0100874BFC /* CustomTabBarLayerProtocol.swift in Sources */, 539996852C27130000671340 /* ConstraintViewDSL.swift in Sources */, 678809E92C6A0D0800EF9046 /* ImageCompressManager.swift in Sources */, + 679650572C6DE688001C4353 /* SignatureViewController.swift in Sources */, EC702542254E1E7500BE1958 /* ClassicWalkthroughViewController.swift in Sources */, 539996882C27130000671340 /* ConstraintMakerFinalizable.swift in Sources */, 675FF4F32C622DEB00E42214 /* ScanSessionPayloadManager.swift in Sources */, @@ -2151,6 +2182,7 @@ 67807F9B2C49325A00D1F168 /* MainView.swift in Sources */, 5399969D2C27130000671340 /* Constraint.swift in Sources */, EC8A9B1D254DCEC600F9AF99 /* File.swift in Sources */, + 6796505C2C6DE8ED001C4353 /* DefaultSignatureSheetViewController.swift in Sources */, 67807F8C2C48F49B00D1F168 /* HandleAppLanguageUseCase.swift in Sources */, 67A20DE12C57BC56009D2F25 /* DocumentsCollectionViewCell.swift in Sources */, 676C30682C6CA6D200C29A43 /* UIButton+CustomColor.swift in Sources */, diff --git a/MiniScanner/Core/Extensions/UIImage+Images.swift b/MiniScanner/Core/Extensions/UIImage+Images.swift index 5afb0265f31cf1f1391311bd237b274022e2e8ec..a2b17570fee0e76e69a1c573c2f17c09e73fa0f6 100644 --- a/MiniScanner/Core/Extensions/UIImage+Images.swift +++ b/MiniScanner/Core/Extensions/UIImage+Images.swift @@ -33,6 +33,8 @@ extension UIImage { static let gallery = UIImage(resource: .galleryIc) static let trash = UIImage(resource: .trashIc) + static let rotateSigLeft = UIImage(resource: .rotateSigLeftIc) + static let rotateSigRight = UIImage(resource: .rotateSigRightIc) } // MARK: - Common system images and icons diff --git a/MiniScanner/Core/Resources/Icons.xcassets/rotate-sig-left-ic.imageset/Contents.json b/MiniScanner/Core/Resources/Icons.xcassets/rotate-sig-left-ic.imageset/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..7025a9b56a7f65587f1a2153a023c58c334c9b71 --- /dev/null +++ b/MiniScanner/Core/Resources/Icons.xcassets/rotate-sig-left-ic.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "rotate-sig-left-ic.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/MiniScanner/Core/Resources/Icons.xcassets/rotate-sig-left-ic.imageset/rotate-sig-left-ic.svg b/MiniScanner/Core/Resources/Icons.xcassets/rotate-sig-left-ic.imageset/rotate-sig-left-ic.svg new file mode 100644 index 0000000000000000000000000000000000000000..0f2f8be23d7f6f13f1aca501f6c501569119e9f7 --- /dev/null +++ b/MiniScanner/Core/Resources/Icons.xcassets/rotate-sig-left-ic.imageset/rotate-sig-left-ic.svg @@ -0,0 +1,3 @@ +<svg width="31" height="30" viewBox="0 0 31 30" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M11.75 17.5L5.5 11.25M5.5 11.25L11.75 5M5.5 11.25H18.625C20.4484 11.25 22.197 11.9743 23.4864 13.2636C24.7757 14.553 25.5 16.3016 25.5 18.125C25.5 19.0278 25.3222 19.9218 24.9767 20.7559C24.6312 21.5901 24.1248 22.348 23.4864 22.9864C22.197 24.2757 20.4484 25 18.625 25H14.25" stroke="black" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/MiniScanner/Core/Resources/Icons.xcassets/rotate-sig-right-ic.imageset/Contents.json b/MiniScanner/Core/Resources/Icons.xcassets/rotate-sig-right-ic.imageset/Contents.json new file mode 100644 index 0000000000000000000000000000000000000000..e98f2f1b5b3b3e1edb2d6d501ede9a3598491835 --- /dev/null +++ b/MiniScanner/Core/Resources/Icons.xcassets/rotate-sig-right-ic.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "rotate-sig-right-ic.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/MiniScanner/Core/Resources/Icons.xcassets/rotate-sig-right-ic.imageset/rotate-sig-right-ic.svg b/MiniScanner/Core/Resources/Icons.xcassets/rotate-sig-right-ic.imageset/rotate-sig-right-ic.svg new file mode 100644 index 0000000000000000000000000000000000000000..cefbb133093fd01f463c0bb0ff4502d14d0c0e5b --- /dev/null +++ b/MiniScanner/Core/Resources/Icons.xcassets/rotate-sig-right-ic.imageset/rotate-sig-right-ic.svg @@ -0,0 +1,3 @@ +<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M18.75 17.5L25 11.25M25 11.25L18.75 5M25 11.25H11.875C10.0516 11.25 8.30295 11.9743 7.01364 13.2636C5.72433 14.553 5 16.3016 5 18.125C5 19.0278 5.17783 19.9218 5.52333 20.7559C5.86883 21.5901 6.37524 22.348 7.01364 22.9864C8.30295 24.2757 10.0516 25 11.875 25H16.25" stroke="black" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/MiniScanner/Modules/EditViewController/EditViewController.swift b/MiniScanner/Modules/EditViewController/EditViewController.swift index 9dfb6041e4f5e1252399805fff905d3b9fc57bbe..b8eacea9d6b232d93fe92532b9d2773567269dfb 100644 --- a/MiniScanner/Modules/EditViewController/EditViewController.swift +++ b/MiniScanner/Modules/EditViewController/EditViewController.swift @@ -574,9 +574,7 @@ extension EditViewController { private func displaySignatureViewController() { - let config = getSignatureViewControllerConfig() - - let signatureVC = EPSignatureViewController(signatureDelegate: self, config: config) + let signatureVC = SignatureViewController(signatureDelegate: self) let nav = UINavigationController(rootViewController: signatureVC) nav.modalPresentationStyle = .fullScreen @@ -584,15 +582,6 @@ extension EditViewController { present(nav, animated: true, completion: nil) } - private func getSignatureViewControllerConfig() -> EPSignatureViewControllerConfig { - - let colors = EPSignatureViewControllerColor(backgroundColor: ColorStyle.base.uiColor, toolbarTintColor: ColorStyle.gray600.uiColor, buttonsTintColor: ColorStyle.gray600.uiColor, signatureBorderColor: ColorStyle.gray450.uiColor, switchColor: ColorStyle.primary.uiColor, saveButtonColor: ColorStyle.primary.uiColor, defaultSignatureButtonColor: ColorStyle.gray550.uiColor) - - let titles = EPSignatureViewControllerTitle(backButtonTitle: .theSignature.localized, deleteSignatureButtonTitle: .deleteSignature.localized, rotateLeftButtonTitle: .rotateLeft.localized, rotateRightButtonTitle: .rotateRight.localized, saveButtonTitle: .save.localized, saveSignatureSwitchTitle: .saveSignature.localized, defaultSignatureButtonTitle: .defaultSignature.localized, useDefaultSignatureButtonTitle: .useDefaultSignature.localized, deleteDefaultSignatureButtonTitle: .deleteDefaultSignature.localized, didntSignAlertTitle: .didntSignAlertTitle.localized, didntSignAlertMessage: .didntSignAlertMessage.localized, didntSignAlertActionTitle: .ok.localized) - - return EPSignatureViewControllerConfig(colors: colors, titles: titles) - } - private func displayOCRViewController() { if let image = scanSession.scannedItems[banner.pagerView.currentIndex].newRenderedImage?.retrieveImage() { @@ -931,12 +920,13 @@ extension EditViewController: FoldersViewControllerDelegate { } // MARK: - EPSignatureDelegate -extension EditViewController: EPSignatureDelegate { - public func epSignature(_: EPSignatureViewController, didCancel error: NSError) { +extension EditViewController: SignatureDelegate { + + func epSignature(_: SignatureViewController, didCancel error: NSError) { print("User canceled") } - public func epSignature(_: EPSignatureViewController, didSign signatureImage: UIImage, boundingRect: CGRect) { + func epSignature(_: SignatureViewController, didSign signatureImage: UIImage, boundingRect: CGRect) { dismiss(animated: true) { [weak self] in guard let self else { return } diff --git a/MiniScanner/Modules/SignatureViewController/DefaultSignatureSheetViewController/DefaultSignatureSheetViewController.swift b/MiniScanner/Modules/SignatureViewController/DefaultSignatureSheetViewController/DefaultSignatureSheetViewController.swift new file mode 100644 index 0000000000000000000000000000000000000000..bae5caaf997f45b3bad67af74a3263e7996867c6 --- /dev/null +++ b/MiniScanner/Modules/SignatureViewController/DefaultSignatureSheetViewController/DefaultSignatureSheetViewController.swift @@ -0,0 +1,78 @@ +// +// DefaultSignatureSheetViewController.swift +// MiniScanner +// +// Created by Mustafa Merza on 8/15/24. +// Copyright © 2024 AppsNectar. All rights reserved. +// + +import UIKit + +protocol DefaultSignatureSheetViewControllerDelegate: AnyObject { + func useDefaultSignature() + func deleteDefaultSignature() +} + +class DefaultSignatureSheetViewController: UIViewController { + + @IBOutlet weak var backgroundView: UIView! + + @IBOutlet weak var useDefaultSignatureButton: UIButton! + @IBOutlet weak var deleteDefaultSignatureButton: UIButton! + + weak var delegate: DefaultSignatureSheetViewControllerDelegate? + + override func viewDidLoad() { + super.viewDidLoad() + setupUI() + } + + init(delegate: DefaultSignatureSheetViewControllerDelegate) { + self.delegate = delegate + super.init(nibName: nil, bundle: nil) + } + + required public init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupUI() { + + setupColors() + + setupFonts() + + backgroundView.layer.cornerRadius = 30 + backgroundView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] + + useDefaultSignatureButton.set(localized: .useDefaultSignature) + + deleteDefaultSignatureButton.set(localized: .deleteDefaultSignature) + } + + private func setupColors() { + + backgroundView.customBackground(.base) + + useDefaultSignatureButton.customTint(.primary) + + deleteDefaultSignatureButton.customTint(.statusFalse) + } + + private func setupFonts() { + useDefaultSignatureButton.set(font: .medium(18)) + deleteDefaultSignatureButton.set(font: .medium(18)) + } + + @IBAction func onTouchUseDefaultSignatureButton(_ sender: Any) { + delegate?.useDefaultSignature() + + dismiss(animated: true) + } + + @IBAction func onTouchDeleteDefaultSignatureButton(_ sender: Any) { + delegate?.deleteDefaultSignature() + + dismiss(animated: true) + } +} diff --git a/MiniScanner/Modules/SignatureViewController/DefaultSignatureSheetViewController/DefaultSignatureSheetViewController.xib b/MiniScanner/Modules/SignatureViewController/DefaultSignatureSheetViewController/DefaultSignatureSheetViewController.xib new file mode 100644 index 0000000000000000000000000000000000000000..c9ec6ef3e1ce60fd6a2b0ef921ad825dd29ef098 --- /dev/null +++ b/MiniScanner/Modules/SignatureViewController/DefaultSignatureSheetViewController/DefaultSignatureSheetViewController.xib @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> + <device id="retina6_12" orientation="portrait" appearance="light"/> + <dependencies> + <deployment identifier="iOS"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/> + <capability name="Safe area layout guides" minToolsVersion="9.0"/> + <capability name="System colors in document resources" minToolsVersion="11.0"/> + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> + </dependencies> + <objects> + <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="DefaultSignatureSheetViewController" customModule="MiniScanner" customModuleProvider="target"> + <connections> + <outlet property="backgroundView" destination="QO4-m1-muu" id="EP1-hJ-CFA"/> + <outlet property="deleteDefaultSignatureButton" destination="m2h-MM-IIa" id="BxH-Ul-trp"/> + <outlet property="useDefaultSignatureButton" destination="8tW-YI-r88" id="vMC-VJ-Wxv"/> + <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/> + </connections> + </placeholder> + <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> + <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT"> + <rect key="frame" x="0.0" y="0.0" width="393" height="160"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="QO4-m1-muu" userLabel="Background View"> + <rect key="frame" x="0.0" y="0.0" width="393" height="160"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> + </view> + <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" spacing="12" translatesAutoresizingMaskIntoConstraints="NO" id="OlB-B5-8Vi"> + <rect key="frame" x="0.0" y="18.666666666666664" width="393" height="122.66666666666669"/> + <subviews> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8tW-YI-r88"> + <rect key="frame" x="0.0" y="0.0" width="393" height="60.666666666666664"/> + <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> + <state key="normal" title="Button"/> + <buttonConfiguration key="configuration" style="plain" title="Use Default Signature"/> + <connections> + <action selector="onTouchUseDefaultSignatureButton:" destination="-1" eventType="touchUpInside" id="9zq-kU-k2y"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="m2h-MM-IIa"> + <rect key="frame" x="0.0" y="72.666666666666657" width="393" height="50"/> + <constraints> + <constraint firstAttribute="height" constant="50" id="aoD-Kx-da0"/> + </constraints> + <buttonConfiguration key="configuration" style="plain" title="Delete Default Signature"/> + <connections> + <action selector="onTouchDeleteDefaultSignatureButton:" destination="-1" eventType="touchUpInside" id="Jyq-wd-8Ed"/> + </connections> + </button> + </subviews> + <constraints> + <constraint firstAttribute="trailing" secondItem="m2h-MM-IIa" secondAttribute="trailing" id="8rv-kv-0mh"/> + <constraint firstItem="m2h-MM-IIa" firstAttribute="height" secondItem="8tW-YI-r88" secondAttribute="height" multiplier="0.826087" id="brC-FB-haw"/> + <constraint firstItem="m2h-MM-IIa" firstAttribute="leading" secondItem="OlB-B5-8Vi" secondAttribute="leading" id="ch4-Rf-b3y"/> + <constraint firstAttribute="trailing" secondItem="8tW-YI-r88" secondAttribute="trailing" id="llK-1r-BuY"/> + <constraint firstItem="8tW-YI-r88" firstAttribute="leading" secondItem="OlB-B5-8Vi" secondAttribute="leading" id="zjy-6W-OVy"/> + </constraints> + </stackView> + </subviews> + <viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> + <constraints> + <constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="OlB-B5-8Vi" secondAttribute="trailing" id="9pa-PS-ZtB"/> + <constraint firstItem="QO4-m1-muu" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="PMi-Zx-bDF"/> + <constraint firstItem="OlB-B5-8Vi" firstAttribute="centerY" secondItem="i5M-Pr-FkT" secondAttribute="centerY" id="fVQ-Md-fAX"/> + <constraint firstAttribute="bottom" secondItem="QO4-m1-muu" secondAttribute="bottom" id="gCb-3o-9bD"/> + <constraint firstItem="fnl-2z-Ty3" firstAttribute="leading" secondItem="OlB-B5-8Vi" secondAttribute="leading" id="iRT-gp-weO"/> + <constraint firstItem="QO4-m1-muu" firstAttribute="trailing" secondItem="fnl-2z-Ty3" secondAttribute="trailing" id="uLe-rL-ylB"/> + <constraint firstItem="fnl-2z-Ty3" firstAttribute="leading" secondItem="QO4-m1-muu" secondAttribute="leading" id="yRs-qD-fRi"/> + </constraints> + <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> + <point key="canvasLocation" x="136.64122137404578" y="264.43661971830988"/> + </view> + </objects> + <resources> + <systemColor name="systemBackgroundColor"> + <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + </systemColor> + </resources> +</document> diff --git a/MiniScanner/Modules/SignatureViewController/SignatureViewController.swift b/MiniScanner/Modules/SignatureViewController/SignatureViewController.swift new file mode 100644 index 0000000000000000000000000000000000000000..15de1d86a23ff00b1bee46ed8e1b4b9594b906ab --- /dev/null +++ b/MiniScanner/Modules/SignatureViewController/SignatureViewController.swift @@ -0,0 +1,247 @@ +// +// SignatureViewController.swift +// MiniScanner +// +// Created by Mustafa Merza on 8/15/24. +// Copyright © 2024 AppsNectar. All rights reserved. +// + +import UIKit +import NBBottomSheet +import EPSignature + +protocol SignatureDelegate: AnyObject { + func epSignature(_: SignatureViewController, didCancel error: NSError) + func epSignature(_: SignatureViewController, didSign signatureImage: UIImage, boundingRect: CGRect) +} + +class SignatureViewController: UIViewController { + + @IBOutlet weak var signatureBackgroundView: UIView! + @IBOutlet weak var signatureView: EPSignatureView! + + + @IBOutlet weak var deleteSignatureLabel: UILabel! + @IBOutlet weak var rotateRightLabel: UILabel! + @IBOutlet weak var rotateLeftLabel: UILabel! + + @IBOutlet weak var defaultSignatureSwitch: CustomSwitch! + @IBOutlet weak var saveDefaultSignatureLabel: UILabel! + + @IBOutlet weak var saveToDefaultsView: UIStackView! + @IBOutlet weak var saveButton: UIButton! + @IBOutlet weak var defaultSignatureButton: UIButton! + + @IBOutlet weak var rotateRightImageView: UIImageView! + + @IBOutlet weak var rotateLeftImageView: UIImageView! + + weak var signatureDelegate: SignatureDelegate? + + override func viewDidLoad() { + super.viewDidLoad() + setupUI() + } + + init(signatureDelegate: SignatureDelegate) { + self.signatureDelegate = signatureDelegate + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private lazy var userDefaultSignatureExists: Bool = { + defaultSignatureExists() + }() + + private lazy var cancelButton: UIBarButtonItem = { + + let button = UIButton(type: .system) + + button.set(localized: .theSignature) + + button.addTarget(self, + action: #selector(onTouchCancelButton), + for: .touchUpInside) + + button.customTint(.gray600) + + return UIBarButtonItem(customView: button) + }() + + private func setupUI() { + + setupColors() + setupFonts() + + setupToolbar() + + signatureBackgroundView.borderWidth = 1 + signatureBackgroundView.cornerRadiuss = 5 + + saveButton.set(localized: .save) + + defaultSignatureButton.set(localized: .defaultSignature) + + saveDefaultSignatureLabel.set(localized: .saveSignature) + + rotateLeftImageView.image = .rotateSigLeft + rotateRightImageView.image = .rotateSigRight + + deleteSignatureLabel.text = .deleteSignature.localized + rotateLeftLabel.text = .rotateLeft.localized + rotateRightLabel.text = .rotateRight.localized + + defaultSignatureSwitch.isOn = false + + defaultSignatureSwitch.padding = 4 + + defaultSignatureSwitch.cornerRadius = 0.5 + defaultSignatureSwitch.thumbCornerRadius = 0.5 + defaultSignatureSwitch.thumbTintColor = .white + defaultSignatureSwitch.animationDuration = 0.5 + defaultSignatureSwitch.thumbSize = CGSize(width: 22, height: 22) + + setupDefaultSignatureViews() + } + + private func setupColors() { + + view.customBackground(.base) + + signatureBackgroundView.borderColor = ColorStyle.gray450.uiColor + + rotateLeftImageView.customTint(.gray600) + rotateRightImageView.customTint(.gray600) + + deleteSignatureLabel.set(color: .gray600) + rotateLeftLabel.set(color: .gray600) + rotateRightLabel.set(color: .gray600) + + saveButton.customTint(.primary) + defaultSignatureButton.customTint(.primary) + + saveDefaultSignatureLabel.set(color: .gray600) + + defaultSignatureSwitch.onTintColor = ColorStyle.primary.uiColor + + defaultSignatureSwitch.offTintColor = ColorStyle.gray350.uiColor + } + + private func setupFonts() { + + deleteSignatureLabel.set(font: .medium(16)) + rotateLeftLabel.set(font: .medium(16)) + rotateRightLabel.set(font: .medium(16)) + + saveDefaultSignatureLabel.set(font: .medium(20)) + } + + private func setupDefaultSignatureViews() { + saveToDefaultsView.isHidden = userDefaultSignatureExists + defaultSignatureButton.isHidden = !userDefaultSignatureExists + } + + private func setupToolbar() { + navigationItem.leftBarButtonItem = cancelButton + } + + // MARK: - Button Actions + + @IBAction func onTouchDefaultSignatureButton(_ sender: Any) { + + let sheet = DefaultSignatureSheetViewController(delegate: self) + + let viewHeight = sheet.view.frame.height + + let configuration = NBBottomSheetConfiguration(animationDuration: 0.4, sheetSize: .fixed(viewHeight)) + + let bottomSheetController = NBBottomSheetController(configuration: configuration) + + bottomSheetController.present(sheet, on: self) + } + + @IBAction func onTouchSaveButton(_ sender: Any) { + if let signature = signatureView.getSignatureAsImage() { + + if defaultSignatureSwitch.isOn { + + let docPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first + + let filePath = (docPath! as NSString).appendingPathComponent("sig.data") + + signatureView.saveSignature(filePath) + } + + signatureDelegate?.epSignature(self, didSign: signature, boundingRect: signatureView.getSignatureBoundsInCanvas()) + + dismiss(animated: true, completion: nil) + } else { + + let alertController = UIAlertController(title: .didntSignAlertTitle.localized, + message: .didntSignAlertMessage.localized, + preferredStyle: .alert) + + let okAction = UIAlertAction(title: .ok.localized, + style: .default, + handler: nil) + + alertController.addAction(okAction) + + present(alertController, animated: true) + } + } + + @objc func onTouchCancelButton() { + signatureDelegate?.epSignature(self, didCancel: NSError(domain: "EPSignatureDomain", code: 1, userInfo: [NSLocalizedDescriptionKey:"User not signed"])) + + dismiss(animated: true, completion: nil) + } + + @IBAction func rotateRightTapped(_ sender: Any) { + + } + + @IBAction func rotateLeftTapped(_ sender: Any) { + + } + + @IBAction func deleteSignatureTapped(_ sender: Any) { + signatureView.clear() + } + + private func defaultSignatureExists() -> Bool { + let docPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first + let filePath = (docPath! as NSString).appendingPathComponent("sig.data") + + return FileManager.default.fileExists(atPath: filePath) + } + + override open func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) { + signatureView.reposition() + } +} + +extension SignatureViewController: DefaultSignatureSheetViewControllerDelegate { + + func useDefaultSignature() { + let docPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first + let filePath = (docPath! as NSString).appendingPathComponent("sig.data") + + userDefaultSignatureExists = true + + setupDefaultSignatureViews() + + signatureView.loadSignature(filePath) + } + + func deleteDefaultSignature() { + userDefaultSignatureExists = false + + setupDefaultSignatureViews() + + signatureView.removeSignature() + } +} diff --git a/MiniScanner/Modules/SignatureViewController/SignatureViewController.xib b/MiniScanner/Modules/SignatureViewController/SignatureViewController.xib new file mode 100644 index 0000000000000000000000000000000000000000..a9df09db48a4e4a1dc8d6534f4e087ea9b2c1c10 --- /dev/null +++ b/MiniScanner/Modules/SignatureViewController/SignatureViewController.xib @@ -0,0 +1,265 @@ +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> + <device id="retina6_12" orientation="portrait" appearance="light"/> + <dependencies> + <deployment identifier="iOS"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/> + <capability name="Safe area layout guides" minToolsVersion="9.0"/> + <capability name="System colors in document resources" minToolsVersion="11.0"/> + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> + </dependencies> + <objects> + <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="SignatureViewController" customModule="MiniScanner" customModuleProvider="target"> + <connections> + <outlet property="defaultSignatureButton" destination="9Yr-SZ-FD7" id="47C-uA-iqp"/> + <outlet property="defaultSignatureSwitch" destination="YrL-f2-HBE" id="l8W-6i-FuW"/> + <outlet property="deleteSignatureLabel" destination="CRK-Nr-0sW" id="LPm-EL-cN2"/> + <outlet property="rotateLeftImageView" destination="3I2-h3-eBW" id="7a4-VW-R7Y"/> + <outlet property="rotateLeftLabel" destination="cix-8y-E9H" id="icw-4N-GRT"/> + <outlet property="rotateRightImageView" destination="RqF-ZN-prb" id="kCj-AN-hB5"/> + <outlet property="rotateRightLabel" destination="haF-Ue-sMc" id="BqB-hC-lQK"/> + <outlet property="saveButton" destination="qQS-X1-GKg" id="Qac-Fn-YIE"/> + <outlet property="saveDefaultSignatureLabel" destination="eMP-L2-lWy" id="b1a-KI-KW7"/> + <outlet property="saveToDefaultsView" destination="VnH-98-Jb1" id="GLG-vl-xpY"/> + <outlet property="signatureBackgroundView" destination="F1r-v6-3cV" id="2r2-YL-0tj"/> + <outlet property="signatureView" destination="L7g-ad-BFn" id="jqB-MO-xF4"/> + <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/> + </connections> + </placeholder> + <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> + <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT"> + <rect key="frame" x="0.0" y="0.0" width="393" height="852"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="F1r-v6-3cV" userLabel="Signature Background View"> + <rect key="frame" x="16" y="75" width="361" height="578"/> + <subviews> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="L7g-ad-BFn" customClass="EPSignatureView"> + <rect key="frame" x="0.0" y="0.0" width="361" height="578"/> + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + </view> + </subviews> + <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + <constraints> + <constraint firstItem="L7g-ad-BFn" firstAttribute="leading" secondItem="F1r-v6-3cV" secondAttribute="leading" id="6io-MP-kC8"/> + <constraint firstItem="L7g-ad-BFn" firstAttribute="top" secondItem="F1r-v6-3cV" secondAttribute="top" id="IC3-yy-7pW"/> + <constraint firstAttribute="bottom" secondItem="L7g-ad-BFn" secondAttribute="bottom" id="gbr-bb-FsH"/> + <constraint firstAttribute="trailing" secondItem="L7g-ad-BFn" secondAttribute="trailing" id="jcH-7F-bZa"/> + </constraints> + </view> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ggF-eZ-UVc" userLabel="Bottom Section"> + <rect key="frame" x="0.0" y="673" width="393" height="145"/> + <subviews> + <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="32" translatesAutoresizingMaskIntoConstraints="NO" id="WbK-mx-4Yl"> + <rect key="frame" x="32" y="0.0" width="329" height="62"/> + <subviews> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="K1i-K0-mEJ"> + <rect key="frame" x="0.0" y="0.0" width="88.333333333333329" height="62"/> + <subviews> + <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="rotate-sig-right-ic" translatesAutoresizingMaskIntoConstraints="NO" id="RqF-ZN-prb"> + <rect key="frame" x="29.333333333333336" y="0.0" width="30" height="30"/> + <constraints> + <constraint firstAttribute="height" constant="30" id="Ey7-r6-ZPn"/> + <constraint firstAttribute="width" constant="30" id="GfI-gf-9wt"/> + </constraints> + </imageView> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="haF-Ue-sMc"> + <rect key="frame" x="23.666666666666661" y="38" width="41.333333333333343" height="20.333333333333329"/> + <fontDescription key="fontDescription" type="system" pointSize="17"/> + <nil key="textColor"/> + <nil key="highlightedColor"/> + </label> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CF5-vF-r8J"> + <rect key="frame" x="0.0" y="0.0" width="88.333333333333329" height="62"/> + <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> + <connections> + <action selector="rotateRightTapped:" destination="-1" eventType="touchUpInside" id="oDc-ZO-pJw"/> + </connections> + </button> + </subviews> + <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + <constraints> + <constraint firstAttribute="trailing" secondItem="CF5-vF-r8J" secondAttribute="trailing" id="2VJ-N4-NqB"/> + <constraint firstItem="haF-Ue-sMc" firstAttribute="centerX" secondItem="K1i-K0-mEJ" secondAttribute="centerX" id="8y0-Ue-TYx"/> + <constraint firstItem="RqF-ZN-prb" firstAttribute="top" secondItem="K1i-K0-mEJ" secondAttribute="top" id="OLL-Ir-uFN"/> + <constraint firstItem="CF5-vF-r8J" firstAttribute="leading" secondItem="K1i-K0-mEJ" secondAttribute="leading" id="Q9f-nT-fkW"/> + <constraint firstItem="haF-Ue-sMc" firstAttribute="top" secondItem="RqF-ZN-prb" secondAttribute="bottom" constant="8" id="YZY-VZ-cfV"/> + <constraint firstAttribute="bottom" secondItem="CF5-vF-r8J" secondAttribute="bottom" id="mfe-QT-Se7"/> + <constraint firstItem="CF5-vF-r8J" firstAttribute="top" secondItem="K1i-K0-mEJ" secondAttribute="top" id="mtK-on-Lvy"/> + <constraint firstItem="RqF-ZN-prb" firstAttribute="centerX" secondItem="K1i-K0-mEJ" secondAttribute="centerX" id="v26-Q3-7Ur"/> + </constraints> + </view> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hz6-e7-t0U"> + <rect key="frame" x="120.33333333333334" y="0.0" width="88.333333333333343" height="62"/> + <subviews> + <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="rotate-sig-left-ic" translatesAutoresizingMaskIntoConstraints="NO" id="3I2-h3-eBW"> + <rect key="frame" x="29.333333333333314" y="0.0" width="30" height="30"/> + <constraints> + <constraint firstAttribute="width" constant="30" id="6I2-U8-GeG"/> + <constraint firstAttribute="height" constant="30" id="hWP-KZ-51C"/> + </constraints> + </imageView> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cix-8y-E9H"> + <rect key="frame" x="23.666666666666661" y="38" width="41.333333333333343" height="20.333333333333329"/> + <fontDescription key="fontDescription" type="system" pointSize="17"/> + <nil key="textColor"/> + <nil key="highlightedColor"/> + </label> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="36I-07-LD2"> + <rect key="frame" x="0.0" y="0.0" width="88.333333333333329" height="62"/> + <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> + <connections> + <action selector="rotateLeftTapped:" destination="-1" eventType="touchUpInside" id="dM1-jm-DvE"/> + </connections> + </button> + </subviews> + <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + <constraints> + <constraint firstItem="36I-07-LD2" firstAttribute="top" secondItem="hz6-e7-t0U" secondAttribute="top" id="0kN-aN-5vH"/> + <constraint firstItem="cix-8y-E9H" firstAttribute="centerX" secondItem="hz6-e7-t0U" secondAttribute="centerX" id="5Hf-gy-32U"/> + <constraint firstItem="cix-8y-E9H" firstAttribute="top" secondItem="3I2-h3-eBW" secondAttribute="bottom" constant="8" id="8JQ-qG-8bV"/> + <constraint firstAttribute="bottom" secondItem="36I-07-LD2" secondAttribute="bottom" id="IdL-Dy-K58"/> + <constraint firstAttribute="trailing" secondItem="36I-07-LD2" secondAttribute="trailing" id="SUR-sg-60g"/> + <constraint firstItem="36I-07-LD2" firstAttribute="leading" secondItem="hz6-e7-t0U" secondAttribute="leading" id="Wn3-Nf-ifN"/> + <constraint firstItem="3I2-h3-eBW" firstAttribute="top" secondItem="hz6-e7-t0U" secondAttribute="top" id="aIE-st-FuY"/> + <constraint firstItem="3I2-h3-eBW" firstAttribute="centerX" secondItem="hz6-e7-t0U" secondAttribute="centerX" id="fE1-e9-kpZ"/> + </constraints> + </view> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LeB-Lu-Shh"> + <rect key="frame" x="240.66666666666671" y="0.0" width="88.333333333333343" height="62"/> + <subviews> + <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="trash-ic" translatesAutoresizingMaskIntoConstraints="NO" id="H4N-c1-6m7"> + <rect key="frame" x="29.333333333333314" y="0.0" width="30" height="30"/> + <color key="tintColor" systemColor="systemRedColor"/> + <constraints> + <constraint firstAttribute="width" constant="30" id="jjf-kE-WD2"/> + <constraint firstAttribute="height" constant="30" id="yhe-Lh-l12"/> + </constraints> + </imageView> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="CRK-Nr-0sW"> + <rect key="frame" x="23.666666666666632" y="38" width="41.333333333333343" height="20.333333333333329"/> + <fontDescription key="fontDescription" type="system" pointSize="17"/> + <nil key="textColor"/> + <nil key="highlightedColor"/> + </label> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4vT-vf-BWf"> + <rect key="frame" x="0.0" y="0.0" width="88.333333333333329" height="62"/> + <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> + <connections> + <action selector="deleteSignatureTapped:" destination="-1" eventType="touchUpInside" id="CcU-jI-cpE"/> + </connections> + </button> + </subviews> + <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + <constraints> + <constraint firstItem="H4N-c1-6m7" firstAttribute="top" secondItem="LeB-Lu-Shh" secondAttribute="top" id="80Q-kf-Jxl"/> + <constraint firstItem="H4N-c1-6m7" firstAttribute="centerX" secondItem="LeB-Lu-Shh" secondAttribute="centerX" id="AnV-QX-js9"/> + <constraint firstItem="CRK-Nr-0sW" firstAttribute="centerX" secondItem="LeB-Lu-Shh" secondAttribute="centerX" id="KEe-8y-duH"/> + <constraint firstItem="4vT-vf-BWf" firstAttribute="top" secondItem="LeB-Lu-Shh" secondAttribute="top" id="PA9-OP-cEb"/> + <constraint firstItem="4vT-vf-BWf" firstAttribute="leading" secondItem="LeB-Lu-Shh" secondAttribute="leading" id="byR-Oo-5QC"/> + <constraint firstAttribute="trailing" secondItem="4vT-vf-BWf" secondAttribute="trailing" id="hmw-xd-UW4"/> + <constraint firstAttribute="bottom" secondItem="4vT-vf-BWf" secondAttribute="bottom" id="srC-Mf-7ux"/> + <constraint firstItem="CRK-Nr-0sW" firstAttribute="top" secondItem="H4N-c1-6m7" secondAttribute="bottom" constant="8" id="vJc-3y-aTl"/> + </constraints> + </view> + </subviews> + <constraints> + <constraint firstAttribute="height" constant="62" id="n2t-bB-kTm"/> + </constraints> + </stackView> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="K7B-Wr-W43"> + <rect key="frame" x="16" y="82" width="361" height="47"/> + <subviews> + <stackView opaque="NO" contentMode="scaleToFill" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="VnH-98-Jb1"> + <rect key="frame" x="16" y="8" width="221.66666666666666" height="31"/> + <subviews> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Save to default signature" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="eMP-L2-lWy"> + <rect key="frame" x="0.0" y="0.0" width="160.66666666666666" height="31"/> + <fontDescription key="fontDescription" type="system" pointSize="14"/> + <color key="textColor" red="0.33333334329999997" green="0.33333334329999997" blue="0.33333334329999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <nil key="highlightedColor"/> + </label> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="YrL-f2-HBE" customClass="CustomSwitch"> + <rect key="frame" x="170.66666666666666" y="0.0" width="51" height="31"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> + <constraints> + <constraint firstAttribute="width" constant="51" id="2yW-dt-X0q"/> + <constraint firstAttribute="height" constant="31" id="9bG-rv-v11"/> + </constraints> + </view> + </subviews> + <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + </stackView> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qQS-X1-GKg"> + <rect key="frame" x="284" y="0.0" width="61" height="47"/> + <state key="normal" title="Button"/> + <buttonConfiguration key="configuration" style="filled" title="Save"/> + <connections> + <action selector="onTouchSaveButton:" destination="-1" eventType="touchUpInside" id="nJS-g0-TJ5"/> + </connections> + </button> + <button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9Yr-SZ-FD7"> + <rect key="frame" x="16" y="0.0" width="156" height="47"/> + <color key="tintColor" systemColor="systemOrangeColor"/> + <state key="normal" title="Button"/> + <buttonConfiguration key="configuration" style="filled" title="Default Signature"/> + <connections> + <action selector="onTouchDefaultSignatureButton:" destination="-1" eventType="touchUpInside" id="7Pn-QF-dp1"/> + </connections> + </button> + </subviews> + <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + <constraints> + <constraint firstItem="9Yr-SZ-FD7" firstAttribute="top" secondItem="K7B-Wr-W43" secondAttribute="top" id="2Ur-hP-IPZ"/> + <constraint firstAttribute="bottom" secondItem="9Yr-SZ-FD7" secondAttribute="bottom" id="74e-Xh-zy3"/> + <constraint firstAttribute="bottom" secondItem="VnH-98-Jb1" secondAttribute="bottom" constant="8" id="G02-d9-xUd"/> + <constraint firstItem="qQS-X1-GKg" firstAttribute="top" secondItem="K7B-Wr-W43" secondAttribute="top" id="c6Z-ZV-V6Q"/> + <constraint firstAttribute="trailing" secondItem="qQS-X1-GKg" secondAttribute="trailing" constant="16" id="efI-Ui-myt"/> + <constraint firstItem="9Yr-SZ-FD7" firstAttribute="leading" secondItem="K7B-Wr-W43" secondAttribute="leading" constant="16" id="keT-9U-oso"/> + <constraint firstItem="VnH-98-Jb1" firstAttribute="top" secondItem="K7B-Wr-W43" secondAttribute="top" constant="8" id="lgd-Uk-rPX"/> + <constraint firstAttribute="bottom" secondItem="qQS-X1-GKg" secondAttribute="bottom" id="oil-U6-fu8"/> + <constraint firstItem="VnH-98-Jb1" firstAttribute="leading" secondItem="K7B-Wr-W43" secondAttribute="leading" constant="16" id="wYe-3m-2Cn"/> + </constraints> + </view> + </subviews> + <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + <constraints> + <constraint firstItem="K7B-Wr-W43" firstAttribute="leading" secondItem="ggF-eZ-UVc" secondAttribute="leading" constant="16" id="2G8-3G-C6e"/> + <constraint firstAttribute="bottom" secondItem="K7B-Wr-W43" secondAttribute="bottom" constant="16" id="ADA-Ja-cdv"/> + <constraint firstItem="K7B-Wr-W43" firstAttribute="top" secondItem="WbK-mx-4Yl" secondAttribute="bottom" constant="20" id="ClK-4m-mp7"/> + <constraint firstItem="WbK-mx-4Yl" firstAttribute="top" secondItem="ggF-eZ-UVc" secondAttribute="top" id="ITB-Fb-iLj"/> + <constraint firstAttribute="trailing" secondItem="WbK-mx-4Yl" secondAttribute="trailing" constant="32" id="Sty-c2-LPy"/> + <constraint firstAttribute="trailing" secondItem="K7B-Wr-W43" secondAttribute="trailing" constant="16" id="abM-0d-LeP"/> + <constraint firstItem="WbK-mx-4Yl" firstAttribute="leading" secondItem="ggF-eZ-UVc" secondAttribute="leading" constant="32" id="j4q-hq-jaJ"/> + </constraints> + </view> + </subviews> + <viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> + <constraints> + <constraint firstItem="ggF-eZ-UVc" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" id="2YY-dC-c45"/> + <constraint firstItem="ggF-eZ-UVc" firstAttribute="top" secondItem="F1r-v6-3cV" secondAttribute="bottom" constant="20" id="8YK-pN-zBJ"/> + <constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="F1r-v6-3cV" secondAttribute="trailing" constant="16" id="B5E-Bv-hxT"/> + <constraint firstItem="fnl-2z-Ty3" firstAttribute="bottom" secondItem="ggF-eZ-UVc" secondAttribute="bottom" id="EFn-IK-kcY"/> + <constraint firstItem="F1r-v6-3cV" firstAttribute="top" secondItem="fnl-2z-Ty3" secondAttribute="top" constant="16" id="Mip-es-hOv"/> + <constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="ggF-eZ-UVc" secondAttribute="trailing" id="onp-J3-2wf"/> + <constraint firstItem="F1r-v6-3cV" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="16" id="pCW-my-gad"/> + </constraints> + <point key="canvasLocation" x="129" y="-11"/> + </view> + </objects> + <resources> + <image name="rotate-sig-left-ic" width="31" height="30"/> + <image name="rotate-sig-right-ic" width="30" height="30"/> + <image name="trash-ic" width="24" height="24"/> + <systemColor name="systemBackgroundColor"> + <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + </systemColor> + <systemColor name="systemOrangeColor"> + <color red="1" green="0.58431372550000005" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + </systemColor> + <systemColor name="systemRedColor"> + <color red="1" green="0.23137254900000001" blue="0.18823529410000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + </systemColor> + </resources> +</document>