From 1c12fe5b40beb770d93a6023bb981c9a384015ee Mon Sep 17 00:00:00 2001 From: Selim Mustafaev Date: Sun, 27 Mar 2022 00:46:33 +0300 Subject: [PATCH] Finished basic variant of "check new number" puller --- .../xcschemes/xcschememanagement.plist | 7 +- .../KeyBackground.colorset/Contents.json | 6 +- .../PlateBackground.colorset/Contents.json | 38 ++++++++++ .../Contents.json | 38 ++++++++++ .../PlateForeground.colorset/Contents.json | 38 ++++++++++ AutoCat2/Components/PlateView/PlateView.swift | 35 +++++++--- AutoCat2/Controllers/CheckController.swift | 70 ++++++------------- AutoCat2/Controllers/MainTabController.swift | 8 +-- AutoCatCore/Models/PlateNumber.swift | 57 +++++++++++++-- 9 files changed, 224 insertions(+), 73 deletions(-) create mode 100644 AutoCat2/Assets.xcassets/Colors/PlateBackground.colorset/Contents.json create mode 100644 AutoCat2/Assets.xcassets/Colors/PlateBackgroundError.colorset/Contents.json create mode 100644 AutoCat2/Assets.xcassets/Colors/PlateForeground.colorset/Contents.json diff --git a/AutoCat2.xcodeproj/xcuserdata/selim.xcuserdatad/xcschemes/xcschememanagement.plist b/AutoCat2.xcodeproj/xcuserdata/selim.xcuserdatad/xcschemes/xcschememanagement.plist index 973e834..e2ffec3 100644 --- a/AutoCat2.xcodeproj/xcuserdata/selim.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/AutoCat2.xcodeproj/xcuserdata/selim.xcuserdatad/xcschemes/xcschememanagement.plist @@ -9,11 +9,16 @@ orderHint 0 - AutoCatCore.xcscheme_^#shared#^_ + AutoCat2.xcscheme_^#shared#^_ orderHint 1 + AutoCatCore.xcscheme_^#shared#^_ + + orderHint + 0 + diff --git a/AutoCat2/Assets.xcassets/Colors/KeyBackground.colorset/Contents.json b/AutoCat2/Assets.xcassets/Colors/KeyBackground.colorset/Contents.json index eb0fccd..c1af852 100644 --- a/AutoCat2/Assets.xcassets/Colors/KeyBackground.colorset/Contents.json +++ b/AutoCat2/Assets.xcassets/Colors/KeyBackground.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "1.000", - "green" : "1.000", - "red" : "1.000" + "blue" : "0xFF", + "green" : "0xFF", + "red" : "0xFF" } }, "idiom" : "universal" diff --git a/AutoCat2/Assets.xcassets/Colors/PlateBackground.colorset/Contents.json b/AutoCat2/Assets.xcassets/Colors/PlateBackground.colorset/Contents.json new file mode 100644 index 0000000..2257e90 --- /dev/null +++ b/AutoCat2/Assets.xcassets/Colors/PlateBackground.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha" : "1.000", + "blue" : "0.152", + "green" : "0.152", + "red" : "0.152" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AutoCat2/Assets.xcassets/Colors/PlateBackgroundError.colorset/Contents.json b/AutoCat2/Assets.xcassets/Colors/PlateBackgroundError.colorset/Contents.json new file mode 100644 index 0000000..dcf9455 --- /dev/null +++ b/AutoCat2/Assets.xcassets/Colors/PlateBackgroundError.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha" : "1.000", + "blue" : "0.000", + "green" : "0.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha" : "1.000", + "blue" : "0.182", + "green" : "0.225", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AutoCat2/Assets.xcassets/Colors/PlateForeground.colorset/Contents.json b/AutoCat2/Assets.xcassets/Colors/PlateForeground.colorset/Contents.json new file mode 100644 index 0000000..945ab6a --- /dev/null +++ b/AutoCat2/Assets.xcassets/Colors/PlateForeground.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.000", + "green" : "0.000", + "red" : "0.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha" : "1.000", + "blue" : "0.866", + "green" : "0.866", + "red" : "0.866" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AutoCat2/Components/PlateView/PlateView.swift b/AutoCat2/Components/PlateView/PlateView.swift index 14bb9df..dba7719 100644 --- a/AutoCat2/Components/PlateView/PlateView.swift +++ b/AutoCat2/Components/PlateView/PlateView.swift @@ -33,6 +33,8 @@ class PlateView: UIView { } } + var onChange: (() -> Void)? + override init(frame: CGRect) { super.init(frame: frame) setup() @@ -81,6 +83,7 @@ class PlateView: UIView { override func layoutSubviews() { super.layoutSubviews() + guard let number = self.number else { return } guard let fgColorMain = UIColor(named: "PlateForeground")?.cgColor else { return } guard let bgColor = UIColor(named: "PlateBackground")?.cgColor else { return } @@ -134,16 +137,26 @@ class PlateView: UIView { let height = fontSize/1.1 + 4 let width = height/PlateView.aspectRatio return CGSize(width: width, height: height) - -// guard self.bounds.width != 0 || self.bounds.height != 0 else { -// return CGSize.zero -// } -// -// let curAspectRatio = self.bounds.height/self.bounds.width -// if curAspectRatio >= PlateView.aspectRatio { -// return CGSize(width: self.bounds.width, height: self.bounds.width*PlateView.aspectRatio) -// } else { -// return CGSize(width: self.bounds.height/PlateView.aspectRatio, height: self.bounds.height) -// } } } + +extension PlateView: UIKeyInput { + + var hasText: Bool { + number?.hasText ?? false + } + + func insertText(_ text: String) { + if number?.insertText(text) == true { + layoutSubviews() + onChange?() + } + } + + func deleteBackward() { + if number?.deleteBackward() == true { + layoutSubviews() + onChange?() + } + } +} diff --git a/AutoCat2/Controllers/CheckController.swift b/AutoCat2/Controllers/CheckController.swift index fcf88f7..4e87987 100644 --- a/AutoCat2/Controllers/CheckController.swift +++ b/AutoCat2/Controllers/CheckController.swift @@ -6,32 +6,33 @@ // import UIKit +import AutoCatCore class CheckController: UIViewController { public var onCheck: ((String) -> Void)? private lazy var keyboardView: PNKeyboard = { - let keyboard = PNKeyboard(target: self.numberField, insets: .zero) + let keyboard = PNKeyboard(target: self.plateView, insets: .zero) keyboard.delegate = self return keyboard }() - - private lazy var numberField: SwiftMaskTextfield = { - let textField = SwiftMaskTextfield() - textField.formatPattern = "@###@@###" - textField.placeholder = "A001AA 777" - textField.borderStyle = .roundedRect - textField.font = .preferredFont(forTextStyle: .largeTitle) - textField.textAlignment = .center - textField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged) - return textField - }() - private let plateView = PlateView(frame: .zero) + private lazy var plateView: PlateView = { + let view = PlateView(frame: .zero) + view.fontSize = 48 + view.number = PlateNumber("") + view.onChange = onNumberChanged + view.setContentHuggingPriority(.defaultHigh, for: .horizontal) + return view + }() - private lazy var checkButton = ACButton(title: "Check", onTap: check) - .enable(false) + private lazy var checkButton: ACButton = { + let button = ACButton(title: "Check", onTap: check) + button.isEnabled = false + button.contentEdgeInsets = .init(top: 0, left: 8, bottom: 0, right: 8) + return button + }() private lazy var stackView: UIStackView = { let stack = UIStackView(arrangedSubviews: [plateView, checkButton]) @@ -43,7 +44,7 @@ class CheckController: UIViewController { private let titleLabel: UILabel = { let label = UILabel() - label.text = "Check new plate number" + label.text = "Check new number" label.font = UIFont.preferredFont(forTextStyle: .headline) label.textAlignment = .center label.translatesAutoresizingMaskIntoConstraints = false @@ -60,35 +61,23 @@ class CheckController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - - //view.backgroundColor = .systemBackground - checkButton.contentEdgeInsets = .init(top: 0, left: 8, bottom: 0, right: 8) view.addSubview(mainStackView) mainStackView.pin(to: view, insets: .init(top: 16, left: 16, bottom: 16, right: 16)) - - NSLayoutConstraint.activate([ - plateView.heightAnchor.constraint(equalToConstant: 40) - ]) - } - - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - - DispatchQueue.main.asyncAfter(deadline: .now() + 2) { - self.numberField.becomeFirstResponder() - } } func check() { - guard let number = numberField.text else { + guard let number = plateView.number, number.isValid else { return } - let numberNormalized = number.filter { !$0.isWhitespace }.uppercased() - numberField.resignFirstResponder() + let numberNormalized = number.asString().filter { !$0.isWhitespace }.uppercased() onCheck?(numberNormalized) } + + func onNumberChanged() { + checkButton.isEnabled = plateView.number?.isValid ?? false + } } extension CheckController: PNKeyboardDelegate { @@ -97,16 +86,3 @@ extension CheckController: PNKeyboardDelegate { check() } } - -extension CheckController: UITextFieldDelegate { - - @objc func textFieldDidChange(_ textField: UITextField) { - guard let text = textField.text else { - self.checkButton.isEnabled = false - return - } - - self.checkButton.isEnabled = text.count >= 8 - } - -} diff --git a/AutoCat2/Controllers/MainTabController.swift b/AutoCat2/Controllers/MainTabController.swift index ee59ade..fb8ce4a 100644 --- a/AutoCat2/Controllers/MainTabController.swift +++ b/AutoCat2/Controllers/MainTabController.swift @@ -41,13 +41,13 @@ class MainTabController: UITabBarController, UITabBarControllerDelegate { func showCheckPuller() { var attributes = EKAttributes.bottomToast attributes.displayDuration = .infinity - attributes.positionConstraints.keyboardRelation = .bind(offset: .none) - attributes.entryBackground = .color(color: .standardBackground) - attributes.screenBackground = .color(color: EKColor(UIColor(white: 0.3, alpha: 0.5))) + attributes.entryBackground = .visualEffect(style: .extra) //.color(color: .standardBackground) + attributes.screenBackground = .color(color: EKColor(UIColor(white: 0, alpha: 0.7))) attributes.roundCorners = .top(radius: 24) attributes.screenInteraction = .dismiss attributes.entryInteraction = .forward - //attributes.shadow = .active(with: .init(color: .black, opacity: 0.2, radius: 24, offset: .zero)) + attributes.entranceAnimation = .init(translate: .init(duration: 0.2)) + attributes.exitAnimation = .init(translate: .init(duration: 0.2)) let checkController = CheckController() checkController.onCheck = { number in diff --git a/AutoCatCore/Models/PlateNumber.swift b/AutoCatCore/Models/PlateNumber.swift index 1eb436d..2fca407 100644 --- a/AutoCatCore/Models/PlateNumber.swift +++ b/AutoCatCore/Models/PlateNumber.swift @@ -1,11 +1,19 @@ import Foundation public class PlateNumber { - private var number: String - private var numberEnglish: String + private var number: String = "" + private var numberEnglish: String = "" + + private let maxLength = 9 + private let mainPartLength = 6 + private let isDigitMask = [false, true, true, true, false, false, true, true, true] public init(_ string: String) { - self.number = string + setNumber(string) + } + + public func setNumber(_ number: String) { + self.number = number self.numberEnglish = String(self.number.map { Constants.pnLettersMap[$0] ?? $0 }) } @@ -14,12 +22,47 @@ public class PlateNumber { } public func mainPart() -> String { - let index = self.numberEnglish.index(self.numberEnglish.startIndex, offsetBy: 6) - return String(self.numberEnglish[.. String { - let index = self.numberEnglish.index(self.numberEnglish.startIndex, offsetBy: 6) - return String(self.numberEnglish[index...]) + guard numberEnglish.count > mainPartLength else { + return "" + } + + return String(self.numberEnglish.dropFirst(mainPartLength)) + } + + public var isValid: Bool { + number.count >= 8 + } + + // MARK: - UIKeyInput + + public var hasText: Bool { + return !number.isEmpty + } + + // Returns true if number was changed + public func insertText(_ text: String) -> Bool { + guard number.count < maxLength, text.count == 1 else { + return false + } + + if text.first?.isNumber == isDigitMask[number.count] { + setNumber(number + text) + return true + } else { + return false + } + } + + public func deleteBackward() -> Bool { + guard !number.isEmpty else { + return false + } + + setNumber(String(number.dropLast())) + return true } }