From 706c47d4dea30b51c78310343410177e9e35242b Mon Sep 17 00:00:00 2001 From: Grigory Ulanov Date: Thu, 27 Jul 2017 15:29:07 +0300 Subject: [PATCH 1/6] CellTextFieldToolBar added --- LeadKitAdditions.podspec | 2 +- .../project.pbxproj | 4 + .../Services/CellFieldsJumpingService.swift | 57 ++++++----- .../Sources/Views/CellTextFieldToolBar.swift | 96 +++++++++++++++++++ 4 files changed, 128 insertions(+), 31 deletions(-) create mode 100644 LeadKitAdditions/Sources/Views/CellTextFieldToolBar.swift diff --git a/LeadKitAdditions.podspec b/LeadKitAdditions.podspec index 07379bb..53d9390 100644 --- a/LeadKitAdditions.podspec +++ b/LeadKitAdditions.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "LeadKitAdditions" - s.version = "0.0.20" + s.version = "0.0.21" s.summary = "iOS framework with a bunch of tools for rapid development" s.homepage = "https://github.com/TouchInstinct/LeadKitAdditions" s.license = "Apache License, Version 2.0" diff --git a/LeadKitAdditions/LeadKitAdditions.xcodeproj/project.pbxproj b/LeadKitAdditions/LeadKitAdditions.xcodeproj/project.pbxproj index fa859bb..cc11ade 100644 --- a/LeadKitAdditions/LeadKitAdditions.xcodeproj/project.pbxproj +++ b/LeadKitAdditions/LeadKitAdditions.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 0A08E37F1F2A13BF00F9AB62 /* CellTextFieldToolBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A08E37E1F2A13BF00F9AB62 /* CellTextFieldToolBar.swift */; }; 248389A288C0A6D7914F0546 /* Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0ED4A1B793EAA73C9E95969F /* Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework */; }; B326804BA6CC8B8BB136A46A /* Pods_LeadKitAdditions_LeadKitAdditions_iOS_Extensions.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CFD5627139CAB27705F75C07 /* Pods_LeadKitAdditions_LeadKitAdditions_iOS_Extensions.framework */; }; CAE698E81E968820000394B0 /* LeadKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = CAE698E61E968820000394B0 /* LeadKitAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -83,6 +84,7 @@ /* Begin PBXFileReference section */ 01605ECA03749D49C27FA3DD /* Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions.release.xcconfig"; path = "Pods/Target Support Files/Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions/Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions.release.xcconfig"; sourceTree = ""; }; + 0A08E37E1F2A13BF00F9AB62 /* CellTextFieldToolBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellTextFieldToolBar.swift; sourceTree = ""; }; 0ED4A1B793EAA73C9E95969F /* Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 49738551AC648B0AFA74E57F /* Pods-LeadKitAdditions-LeadKitAdditions iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeadKitAdditions-LeadKitAdditions iOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-LeadKitAdditions-LeadKitAdditions iOS/Pods-LeadKitAdditions-LeadKitAdditions iOS.debug.xcconfig"; sourceTree = ""; }; 7B7F57C5E5275C4D8DC71992 /* Pods_LeadKitAdditions.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKitAdditions.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -323,6 +325,7 @@ ED0C33FF1F2906EC00FAE9FD /* Views */ = { isa = PBXGroup; children = ( + 0A08E37E1F2A13BF00F9AB62 /* CellTextFieldToolBar.swift */, ED0C34001F2906EC00FAE9FD /* CellTextField */, ); path = Views; @@ -585,6 +588,7 @@ ED0C34451F2906EC00FAE9FD /* CellTextField.swift in Sources */, ED0C34271F2906EC00FAE9FD /* CellFieldsToolBarProtocol.swift in Sources */, ED0C34291F2906EC00FAE9FD /* CellFieldValidationProtocol.swift in Sources */, + 0A08E37F1F2A13BF00F9AB62 /* CellTextFieldToolBar.swift in Sources */, ED0C34031F2906EC00FAE9FD /* ApiResponse.swift in Sources */, ED0C34071F2906EC00FAE9FD /* LoadingBarButton.swift in Sources */, ED0C34251F2906EC00FAE9FD /* CellFieldMaskProtocol.swift in Sources */, diff --git a/LeadKitAdditions/Sources/Services/CellFieldsJumpingService.swift b/LeadKitAdditions/Sources/Services/CellFieldsJumpingService.swift index 6406c78..692ff28 100644 --- a/LeadKitAdditions/Sources/Services/CellFieldsJumpingService.swift +++ b/LeadKitAdditions/Sources/Services/CellFieldsJumpingService.swift @@ -77,36 +77,33 @@ class CellFieldsJumpingService { } private func toolBar(for field: CellFieldJumpingProtocol, with index: Int) -> UIToolbar { - // hotfix for project builing - // todo: @GrigoryUlanov - return UIToolbar() -// let toolBar = CellTextFieldToolBar() -// toolBar.canGoForward = cellFields.nextActive(from: index) != nil -// toolBar.canGoBackward = cellFields.previousActive(from: index) != nil -// -// toolBar.needArrows = config.toolBarNeedArrows -// -// toolBar.shouldGoForward.asObservable() -// .subscribe(onNext: { [weak self] in -// self?.shouldGoForwardAction(from: index) -// }) -// .addDisposableTo(disposeBag) -// -// toolBar.shouldGoBackward.asObservable() -// .subscribe(onNext: { [weak self] in -// if let previousActive = self?.cellFields.previousActive(from: index) { -// previousActive.shouldBecomeFirstResponder.onNext() -// } -// }) -// .addDisposableTo(disposeBag) -// -// toolBar.shouldEndEditing.asObservable() -// .subscribe(onNext: { -// field.shouldResignFirstResponder.onNext() -// }) -// .addDisposableTo(disposeBag) -// -// return toolBar + let toolBar = CellTextFieldToolBar() + toolBar.canGoForward = cellFields.nextActive(from: index) != nil + toolBar.canGoBackward = cellFields.previousActive(from: index) != nil + + toolBar.needArrows = config.toolBarNeedArrows + + toolBar.shouldGoForward.asObservable() + .subscribe(onNext: { [weak self] in + self?.shouldGoForwardAction(from: index) + }) + .addDisposableTo(disposeBag) + + toolBar.shouldGoBackward.asObservable() + .subscribe(onNext: { [weak self] in + if let previousActive = self?.cellFields.previousActive(from: index) { + previousActive.shouldBecomeFirstResponder.onNext() + } + }) + .addDisposableTo(disposeBag) + + toolBar.shouldEndEditing.asObservable() + .subscribe(onNext: { + field.shouldResignFirstResponder.onNext() + }) + .addDisposableTo(disposeBag) + + return toolBar } private func shouldGoForwardAction(from index: Int) { diff --git a/LeadKitAdditions/Sources/Views/CellTextFieldToolBar.swift b/LeadKitAdditions/Sources/Views/CellTextFieldToolBar.swift new file mode 100644 index 0000000..108b913 --- /dev/null +++ b/LeadKitAdditions/Sources/Views/CellTextFieldToolBar.swift @@ -0,0 +1,96 @@ +import UIKit +import RxSwift +import RxCocoa +import LeadKit + +class CellTextFieldToolBar: UIToolbar, CellFieldsToolBarProtocol { + + private let buttonSpace: CGFloat = 20 + private let customSkyColor = UIColor(hex6: 0x0A84DF) + + // MARK: - CellFieldsToolBarProtocol + + var needArrows: Bool = true + + var canGoForward: Bool = false { + didSet { + forwardButton.isEnabled = canGoForward + } + } + var canGoBackward: Bool = false { + didSet { + backButton.isEnabled = canGoBackward + } + } + + var shouldGoForward = PublishSubject() + var shouldGoBackward = PublishSubject() + var shouldEndEditing = PublishSubject() + + // MARK: - UIBarButtonItems + + private(set) lazy var backButton: UIBarButtonItem = { + let backButton = UIBarButtonItem(image: #imageLiteral(resourceName: "keyboard_back"), + style: .plain, + target: self, + action: #selector(backAction)) + return backButton + }() + + private(set) lazy var forwardButton: UIBarButtonItem = { + let forwardButton = UIBarButtonItem(image: #imageLiteral(resourceName: "keyboard_forward"), + style: .plain, + target: self, + action: #selector(forwardAction)) + return forwardButton + }() + + private(set) lazy var closeButton: UIBarButtonItem = { + let doneButton = UIBarButtonItem(barButtonSystemItem: .done, + target: self, + action: #selector(doneAction)) + return doneButton + }() + + // MARK: - Initialization + + override init(frame: CGRect) { + super.init(frame: frame) + initialization() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + initialization() + } + + private func initialization() { + barStyle = .default + isTranslucent = true + sizeToFit() + + let leftSpacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) + let buttonsSpacer1 = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil) + buttonsSpacer1.width = buttonSpace + let buttonsSpacer2 = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil) + buttonsSpacer2.width = buttonSpace + + setItems([leftSpacer, backButton, buttonsSpacer1, forwardButton, buttonsSpacer2, closeButton], animated: true) + items?.forEach { $0.tintColor = customSkyColor } + } + + // MARK: - Actions + + @objc private func backAction() { + shouldGoBackward.onNext() + } + + @objc private func forwardAction() { + shouldGoForward.onNext() + } + + @objc private func doneAction() { + shouldEndEditing.onNext() + } + +} From 192c7b0fe5a4dd65d68981331e738c471a20474b Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Fri, 28 Jul 2017 04:42:45 +0300 Subject: [PATCH 2/6] Add. Missing pod for subspec & license --- LICENSE | 201 ++++++++++++++++++ LeadKitAdditions.podspec | 2 + .../project.pbxproj | 2 + 3 files changed, 205 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LeadKitAdditions.podspec b/LeadKitAdditions.podspec index 53d9390..dfc9623 100644 --- a/LeadKitAdditions.podspec +++ b/LeadKitAdditions.podspec @@ -34,6 +34,8 @@ Pod::Spec.new do |s| ss.dependency "LeadKit/Core-iOS-Extension", '~> 0.5' ss.dependency "KeychainAccess", '3.0.2' ss.dependency "IDZSwiftCommonCrypto", '0.9.1' + ss.dependency "InputMask", '2.2.5' + ss.dependency "SwiftValidator", '4.0.0' end s.default_subspec = 'Core' diff --git a/LeadKitAdditions/LeadKitAdditions.xcodeproj/project.pbxproj b/LeadKitAdditions/LeadKitAdditions.xcodeproj/project.pbxproj index cc11ade..44d3e55 100644 --- a/LeadKitAdditions/LeadKitAdditions.xcodeproj/project.pbxproj +++ b/LeadKitAdditions/LeadKitAdditions.xcodeproj/project.pbxproj @@ -79,6 +79,7 @@ ED0C34461F2906EC00FAE9FD /* CellTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C34011F2906EC00FAE9FD /* CellTextField.swift */; }; ED0C34471F2906EC00FAE9FD /* CellTextFieldViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C34021F2906EC00FAE9FD /* CellTextFieldViewModel.swift */; }; ED0C34481F2906EC00FAE9FD /* CellTextFieldViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C34021F2906EC00FAE9FD /* CellTextFieldViewModel.swift */; }; + ED69E7E81F2AC7CC00C74895 /* CellTextFieldToolBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A08E37E1F2A13BF00F9AB62 /* CellTextFieldToolBar.swift */; }; EFBD55921EBB9A980062AA63 /* LeadKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = CAE698E61E968820000394B0 /* LeadKitAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ @@ -630,6 +631,7 @@ ED0C340E1F2906EC00FAE9FD /* PassCodeHolder.swift in Sources */, ED0C34461F2906EC00FAE9FD /* CellTextField.swift in Sources */, ED0C34281F2906EC00FAE9FD /* CellFieldsToolBarProtocol.swift in Sources */, + ED69E7E81F2AC7CC00C74895 /* CellTextFieldToolBar.swift in Sources */, ED0C342A1F2906EC00FAE9FD /* CellFieldValidationProtocol.swift in Sources */, ED0C34041F2906EC00FAE9FD /* ApiResponse.swift in Sources */, ED0C34081F2906EC00FAE9FD /* LoadingBarButton.swift in Sources */, From 9c04cbdc328eb8e3bee828ac47602dda4b95e419 Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Fri, 28 Jul 2017 05:02:10 +0300 Subject: [PATCH 3/6] Add. Code quality --- .gitmodules | 3 + LeadKitAdditions/.swiftlint.yml | 122 +++++++++++++++++- LeadKitAdditions/.tailor.yml | 4 - .../project.pbxproj | 30 ++--- .../ViewModel/BasePassCodeViewModel.swift | 2 + .../Sources/Services/MaskFieldTextProxy.swift | 3 + .../ValidationService/ValidationItem.swift | 2 + .../CellTextFieldViewModel.swift | 3 + code-quality | 1 + 9 files changed, 148 insertions(+), 22 deletions(-) create mode 100644 .gitmodules delete mode 100644 LeadKitAdditions/.tailor.yml create mode 160000 code-quality diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..53b16c0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "code-quality"] + path = code-quality + url = https://github.com/TouchInstinct/code-quality-ios diff --git a/LeadKitAdditions/.swiftlint.yml b/LeadKitAdditions/.swiftlint.yml index 307a6ea..cd926c2 100644 --- a/LeadKitAdditions/.swiftlint.yml +++ b/LeadKitAdditions/.swiftlint.yml @@ -1,8 +1,9 @@ disabled_rules: - - variable_name + - identifier_name excluded: - Carthage - Pods + line_length: 128 type_body_length: - 500 # warning @@ -16,6 +17,121 @@ custom_rules: uiwebview_disabled: included: ".*.swift" name: "UIWebView Usage Disabled" - regex: "(UIWebView)" + regex: 'UIWebView' message: "Do not use UIWebView. Use WKWebView Instead. https://developer.apple.com/reference/uikit/uiwebview" - severity: error \ No newline at end of file + severity: error + + native_print: + name: "print -> DDLog" + regex: '(print|NSLog)\(' + message: "Please use CocoaLumberjack instead `print` and `NSlog`" + severity: error + + zero: + name: "Short .zero" + regex: '\(top: 0, left: 0, bottom: 0, right: 0\)' + message: "Please use short init `.zero`." + severity: error + + private_variable: + name: "Private variable" + regex: '(?|>=)\s*0' + message: "Prefer checking `isEmpty` over comparing `count` to zero." + severity: warning + + # Should be { braces_body } instead of {braces_body} + spaces_around_braces: + included: ".*.swift" + name: "Spaces around the braces" + regex: '(([A-Za-z0-9])[\{\}])|([\{\}]([A-Za-z0-9]))' + message: "No spaces around the braces" + severity: error + match_kinds: + - attribute.builtin + - attribute.id + - buildconfig.id + - buildconfig.keyword + - identifier + - keyword + - objectliteral + - parameter + - placeholder + - typeidentifier + + inout_keyword: + name: "Inout" + regex: 'inout' + message: "Don't use inout arguments" + severity: error + match_kinds: keyword + + continue_keyword: + name: "Continue" + regex: 'continue' + message: "Don't use continue instruction" + severity: error + match_kinds: keyword + + cyrillic_strings: + name: "Cyrillic strings" + regex: '[а-яА-Я]+' + message: "Localize or translate" + severity: error + match_kinds: + - identifier + - string + + simple_ban: + name: "Simple type name" + regex: '(class|struct)(.)+[sS]imple(.)+\{' + message: "Don't use 'simple' in type name, use 'default' or 'base' instead" + severity: warning diff --git a/LeadKitAdditions/.tailor.yml b/LeadKitAdditions/.tailor.yml deleted file mode 100644 index 1bee518..0000000 --- a/LeadKitAdditions/.tailor.yml +++ /dev/null @@ -1,4 +0,0 @@ -exclude: - - 'Pods' - - 'Carthage' - - 'RxAlamofire' diff --git a/LeadKitAdditions/LeadKitAdditions.xcodeproj/project.pbxproj b/LeadKitAdditions/LeadKitAdditions.xcodeproj/project.pbxproj index 44d3e55..d511837 100644 --- a/LeadKitAdditions/LeadKitAdditions.xcodeproj/project.pbxproj +++ b/LeadKitAdditions/LeadKitAdditions.xcodeproj/project.pbxproj @@ -385,7 +385,6 @@ CAE698E11E968820000394B0 /* Resources */, 94F6E1BA5AD68C6E2F10062B /* [CP] Copy Pods Resources */, CAE6990A1E969A7A000394B0 /* Swiftlint */, - CAE6990B1E969A8D000394B0 /* Tailor */, ); buildRules = ( ); @@ -406,6 +405,7 @@ EFBD556D1EBB87100062AA63 /* Headers */, EFBD556E1EBB87100062AA63 /* Resources */, 808FF5474C0E1574D405EFAF /* [CP] Copy Pods Resources */, + ED69E7E91F2AD0E000C74895 /* Swiftlint */, ); buildRules = ( ); @@ -531,20 +531,6 @@ shellPath = /bin/sh; shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi"; }; - CAE6990B1E969A8D000394B0 /* Tailor */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = Tailor; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if hash tailor 2>/dev/null; then\n tailor\nelse\n echo \"warning: Please install Tailor from https://tailor.sh\"\nfi"; - }; E8E82E34792B38EF225575D7 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -560,6 +546,20 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; + ED69E7E91F2AD0E000C74895 /* Swiftlint */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = Swiftlint; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift b/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift index 3fbd333..b78d9a4 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift @@ -52,7 +52,9 @@ open class BasePassCodeViewModel: BaseViewModel { return passCodeControllerStateHolder.asDriver() } + // swiftlint:disable private_variable public let passCodeText = Variable(nil) + // swiftlint:enable private_variable fileprivate var attemptsNumber = 0 diff --git a/LeadKitAdditions/Sources/Services/MaskFieldTextProxy.swift b/LeadKitAdditions/Sources/Services/MaskFieldTextProxy.swift index e28c424..cfd4ead 100644 --- a/LeadKitAdditions/Sources/Services/MaskFieldTextProxy.swift +++ b/LeadKitAdditions/Sources/Services/MaskFieldTextProxy.swift @@ -6,7 +6,10 @@ class MaskFieldTextProxy: NSObject { private var disposeBag = DisposeBag() + // swiftlint:disable private_variable let text = Variable("") + // swiftlint:enable private_variable + fileprivate let isCompleteHolder = Variable(false) var isComplete: Bool { return isCompleteHolder.value diff --git a/LeadKitAdditions/Sources/Services/ValidationService/ValidationItem.swift b/LeadKitAdditions/Sources/Services/ValidationService/ValidationItem.swift index 902ac93..3204d53 100644 --- a/LeadKitAdditions/Sources/Services/ValidationService/ValidationItem.swift +++ b/LeadKitAdditions/Sources/Services/ValidationService/ValidationItem.swift @@ -43,7 +43,9 @@ class ValidationItem { return validationStateHolder.asObservable() } + // swiftlint:disable private_variable let text = Variable(nil) + // swiftlint:enable private_variable private(set) var rules: [Rule] = [] diff --git a/LeadKitAdditions/Sources/Views/CellTextField/CellTextFieldViewModel.swift b/LeadKitAdditions/Sources/Views/CellTextField/CellTextFieldViewModel.swift index c154ede..1c9ffcd 100644 --- a/LeadKitAdditions/Sources/Views/CellTextField/CellTextFieldViewModel.swift +++ b/LeadKitAdditions/Sources/Views/CellTextField/CellTextFieldViewModel.swift @@ -3,7 +3,10 @@ import RxSwift class CellTextFieldViewModel: CellFieldJumpingProtocol { + // swiftlint:disable private_variable let text: Variable + // swiftlint:enable private_variable + let placeholder: String let textFieldSettingsBlock: ItemSettingsBlock? diff --git a/code-quality b/code-quality new file mode 160000 index 0000000..817e845 --- /dev/null +++ b/code-quality @@ -0,0 +1 @@ +Subproject commit 817e845592f02fb0d22bf52ff9bb8db3210ddd89 From f93066a1f4df553a52b0f710ec1b7fe1b28e9461 Mon Sep 17 00:00:00 2001 From: Grigory Ulanov Date: Fri, 28 Jul 2017 07:52:57 +0300 Subject: [PATCH 4/6] pull request fix --- .../Sources/Views/CellTextFieldToolBar.swift | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/LeadKitAdditions/Sources/Views/CellTextFieldToolBar.swift b/LeadKitAdditions/Sources/Views/CellTextFieldToolBar.swift index 108b913..2bebb40 100644 --- a/LeadKitAdditions/Sources/Views/CellTextFieldToolBar.swift +++ b/LeadKitAdditions/Sources/Views/CellTextFieldToolBar.swift @@ -6,7 +6,6 @@ import LeadKit class CellTextFieldToolBar: UIToolbar, CellFieldsToolBarProtocol { private let buttonSpace: CGFloat = 20 - private let customSkyColor = UIColor(hex6: 0x0A84DF) // MARK: - CellFieldsToolBarProtocol @@ -29,8 +28,19 @@ class CellTextFieldToolBar: UIToolbar, CellFieldsToolBarProtocol { // MARK: - UIBarButtonItems + var backButtonImage: UIImage = #imageLiteral(resourceName: "keyboard_back") { + didSet { + backButton.image = backButtonImage + } + } + var forwardButtonImage: UIImage = #imageLiteral(resourceName: "keyboard_forward") { + didSet { + backButton.image = backButtonImage + } + } + private(set) lazy var backButton: UIBarButtonItem = { - let backButton = UIBarButtonItem(image: #imageLiteral(resourceName: "keyboard_back"), + let backButton = UIBarButtonItem(image: self.backButtonImage, style: .plain, target: self, action: #selector(backAction)) @@ -38,7 +48,7 @@ class CellTextFieldToolBar: UIToolbar, CellFieldsToolBarProtocol { }() private(set) lazy var forwardButton: UIBarButtonItem = { - let forwardButton = UIBarButtonItem(image: #imageLiteral(resourceName: "keyboard_forward"), + let forwardButton = UIBarButtonItem(image: self.forwardButtonImage, style: .plain, target: self, action: #selector(forwardAction)) @@ -67,16 +77,17 @@ class CellTextFieldToolBar: UIToolbar, CellFieldsToolBarProtocol { private func initialization() { barStyle = .default isTranslucent = true + tintColor = UIColor(hex6: 0x0A84DF) sizeToFit() let leftSpacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) - let buttonsSpacer1 = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil) - buttonsSpacer1.width = buttonSpace - let buttonsSpacer2 = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil) - buttonsSpacer2.width = buttonSpace + let firstButtonsSpacer = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil) + firstButtonsSpacer.width = buttonSpace + let secondButtonsSpacer = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil) + secondButtonsSpacer.width = buttonSpace - setItems([leftSpacer, backButton, buttonsSpacer1, forwardButton, buttonsSpacer2, closeButton], animated: true) - items?.forEach { $0.tintColor = customSkyColor } + setItems([leftSpacer, backButton, firstButtonsSpacer, forwardButton, secondButtonsSpacer, closeButton], animated: true) + items?.forEach { $0.tintColor = tintColor } } // MARK: - Actions From 638399eb2d2dac7cf251ddbd6f15e1eb024c89ae Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Fri, 28 Jul 2017 14:24:38 +0300 Subject: [PATCH 5/6] Fix. Linting & rules --- LeadKitAdditions/.swiftlint.yml | 138 +----------------- .../View/BasePassCodeViewController.swift | 4 +- .../ViewModel/BasePassCodeViewModel.swift | 14 +- .../Sources/Services/MaskFieldTextProxy.swift | 4 +- .../ValidationService/ValidationItem.swift | 4 +- .../Views/CellTextField/CellTextField.swift | 6 +- .../CellTextFieldViewModel.swift | 14 +- 7 files changed, 31 insertions(+), 153 deletions(-) mode change 100644 => 120000 LeadKitAdditions/.swiftlint.yml diff --git a/LeadKitAdditions/.swiftlint.yml b/LeadKitAdditions/.swiftlint.yml deleted file mode 100644 index cd926c2..0000000 --- a/LeadKitAdditions/.swiftlint.yml +++ /dev/null @@ -1,137 +0,0 @@ -disabled_rules: - - identifier_name -excluded: - - Carthage - - Pods - -line_length: 128 -type_body_length: - - 500 # warning - - 700 # error -file_length: - warning: 500 - error: 1200 -warning_threshold: 1 - -custom_rules: - uiwebview_disabled: - included: ".*.swift" - name: "UIWebView Usage Disabled" - regex: 'UIWebView' - message: "Do not use UIWebView. Use WKWebView Instead. https://developer.apple.com/reference/uikit/uiwebview" - severity: error - - native_print: - name: "print -> DDLog" - regex: '(print|NSLog)\(' - message: "Please use CocoaLumberjack instead `print` and `NSlog`" - severity: error - - zero: - name: "Short .zero" - regex: '\(top: 0, left: 0, bottom: 0, right: 0\)' - message: "Please use short init `.zero`." - severity: error - - private_variable: - name: "Private variable" - regex: '(?|>=)\s*0' - message: "Prefer checking `isEmpty` over comparing `count` to zero." - severity: warning - - # Should be { braces_body } instead of {braces_body} - spaces_around_braces: - included: ".*.swift" - name: "Spaces around the braces" - regex: '(([A-Za-z0-9])[\{\}])|([\{\}]([A-Za-z0-9]))' - message: "No spaces around the braces" - severity: error - match_kinds: - - attribute.builtin - - attribute.id - - buildconfig.id - - buildconfig.keyword - - identifier - - keyword - - objectliteral - - parameter - - placeholder - - typeidentifier - - inout_keyword: - name: "Inout" - regex: 'inout' - message: "Don't use inout arguments" - severity: error - match_kinds: keyword - - continue_keyword: - name: "Continue" - regex: 'continue' - message: "Don't use continue instruction" - severity: error - match_kinds: keyword - - cyrillic_strings: - name: "Cyrillic strings" - regex: '[а-яА-Я]+' - message: "Localize or translate" - severity: error - match_kinds: - - identifier - - string - - simple_ban: - name: "Simple type name" - regex: '(class|struct)(.)+[sS]imple(.)+\{' - message: "Don't use 'simple' in type name, use 'default' or 'base' instead" - severity: warning diff --git a/LeadKitAdditions/.swiftlint.yml b/LeadKitAdditions/.swiftlint.yml new file mode 120000 index 0000000..7fc22af --- /dev/null +++ b/LeadKitAdditions/.swiftlint.yml @@ -0,0 +1 @@ +../code-quality/.swiftlint.yml \ No newline at end of file diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift index 11591ce..ccb7918 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/View/BasePassCodeViewController.swift @@ -212,11 +212,11 @@ extension BasePassCodeViewController: ConfigurableController { open func bindViews() { fakeTextField.rx.text.asDriver() - .do(onNext: { [weak self] text in + .drive(onNext: { [weak self] text in self?.setStates(for: text ?? "") self?.hideError() + self?.viewModel.setPassCodeText(text) }) - .drive(viewModel.passCodeText) .addDisposableTo(disposeBag) viewModel.validationResult diff --git a/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift b/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift index b78d9a4..f17ca41 100644 --- a/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift +++ b/LeadKitAdditions/Sources/Controllers/PassCode/ViewModel/BasePassCodeViewModel.swift @@ -52,9 +52,7 @@ open class BasePassCodeViewModel: BaseViewModel { return passCodeControllerStateHolder.asDriver() } - // swiftlint:disable private_variable - public let passCodeText = Variable(nil) - // swiftlint:enable private_variable + private let passCodeText = Variable(nil) fileprivate var attemptsNumber = 0 @@ -110,6 +108,16 @@ open class BasePassCodeViewModel: BaseViewModel { .addDisposableTo(disposeBag) } + // MARK: - Public + + public var passCodeTextValue: String? { + return passCodeText.value + } + + public func setPassCodeText(_ value: String?) { + passCodeText.value = value + } + public func reset() { passCodeText.value = nil validationResultHolder.value = nil diff --git a/LeadKitAdditions/Sources/Services/MaskFieldTextProxy.swift b/LeadKitAdditions/Sources/Services/MaskFieldTextProxy.swift index cfd4ead..a275c51 100644 --- a/LeadKitAdditions/Sources/Services/MaskFieldTextProxy.swift +++ b/LeadKitAdditions/Sources/Services/MaskFieldTextProxy.swift @@ -6,9 +6,7 @@ class MaskFieldTextProxy: NSObject { private var disposeBag = DisposeBag() - // swiftlint:disable private_variable - let text = Variable("") - // swiftlint:enable private_variable + fileprivate let text = Variable("") fileprivate let isCompleteHolder = Variable(false) var isComplete: Bool { diff --git a/LeadKitAdditions/Sources/Services/ValidationService/ValidationItem.swift b/LeadKitAdditions/Sources/Services/ValidationService/ValidationItem.swift index 3204d53..e848cd5 100644 --- a/LeadKitAdditions/Sources/Services/ValidationService/ValidationItem.swift +++ b/LeadKitAdditions/Sources/Services/ValidationService/ValidationItem.swift @@ -43,9 +43,7 @@ class ValidationItem { return validationStateHolder.asObservable() } - // swiftlint:disable private_variable - let text = Variable(nil) - // swiftlint:enable private_variable + private let text = Variable(nil) private(set) var rules: [Rule] = [] diff --git a/LeadKitAdditions/Sources/Views/CellTextField/CellTextField.swift b/LeadKitAdditions/Sources/Views/CellTextField/CellTextField.swift index 4ccf4ac..0377b83 100644 --- a/LeadKitAdditions/Sources/Views/CellTextField/CellTextField.swift +++ b/LeadKitAdditions/Sources/Views/CellTextField/CellTextField.swift @@ -24,14 +24,16 @@ class CellTextField: UITextField { inputAccessoryView = viewModel.toolBar returnKeyType = viewModel.returnButtonType - text = viewModel.text.value + text = viewModel.textValue placeholder = viewModel.placeholder viewModel.textFieldSettingsBlock?(self) viewModel.bind(for: self, to: disposeBag) rx.text.asDriver() - .drive(viewModel.text) + .drive(onNext: { + viewModel.setTextValue($0) + }) .addDisposableTo(disposeBag) rx.controlEvent(.editingDidEndOnExit).asObservable() diff --git a/LeadKitAdditions/Sources/Views/CellTextField/CellTextFieldViewModel.swift b/LeadKitAdditions/Sources/Views/CellTextField/CellTextFieldViewModel.swift index 1c9ffcd..b3508f8 100644 --- a/LeadKitAdditions/Sources/Views/CellTextField/CellTextFieldViewModel.swift +++ b/LeadKitAdditions/Sources/Views/CellTextField/CellTextFieldViewModel.swift @@ -3,9 +3,7 @@ import RxSwift class CellTextFieldViewModel: CellFieldJumpingProtocol { - // swiftlint:disable private_variable - let text: Variable - // swiftlint:enable private_variable + private let text: Variable let placeholder: String @@ -30,4 +28,14 @@ class CellTextFieldViewModel: CellFieldJumpingProtocol { self.textFieldSettingsBlock = textFieldSettingsBlock } + // MARK: - Internal + + var textValue: String? { + return text.value + } + + func setTextValue(_ value: String?) { + text.value = value + } + } From 73ba56f3c75338cdd53a24e1645c948c87f9f381 Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Fri, 28 Jul 2017 14:28:07 +0300 Subject: [PATCH 6/6] Fix. Resource name --- LeadKitAdditions/Sources/Views/CellTextFieldToolBar.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LeadKitAdditions/Sources/Views/CellTextFieldToolBar.swift b/LeadKitAdditions/Sources/Views/CellTextFieldToolBar.swift index 2bebb40..da15cb9 100644 --- a/LeadKitAdditions/Sources/Views/CellTextFieldToolBar.swift +++ b/LeadKitAdditions/Sources/Views/CellTextFieldToolBar.swift @@ -28,12 +28,12 @@ class CellTextFieldToolBar: UIToolbar, CellFieldsToolBarProtocol { // MARK: - UIBarButtonItems - var backButtonImage: UIImage = #imageLiteral(resourceName: "keyboard_back") { + var backButtonImage: UIImage? { didSet { backButton.image = backButtonImage } } - var forwardButtonImage: UIImage = #imageLiteral(resourceName: "keyboard_forward") { + var forwardButtonImage: UIImage? { didSet { backButton.image = backButtonImage }