Compare commits
63 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
4c4db7e5a5 | |
|
|
b6fe2474f5 | |
|
|
91d4eb2dd9 | |
|
|
42afb31d73 | |
|
|
e22c6813cb | |
|
|
0e99ac3ccc | |
|
|
de0b3b9da7 | |
|
|
6daa551dd3 | |
|
|
ffffc847f7 | |
|
|
4904449b85 | |
|
|
131d3c7b78 | |
|
|
4fd075cbc8 | |
|
|
b91144f0ff | |
|
|
8320179e01 | |
|
|
cb8a37f9c9 | |
|
|
0f0a1861f1 | |
|
|
fc168d6d24 | |
|
|
4006a3570f | |
|
|
c3be916033 | |
|
|
beecb2955b | |
|
|
817be88e76 | |
|
|
98719044b0 | |
|
|
246bd21260 | |
|
|
a63bfe6e7f | |
|
|
61ae9439d3 | |
|
|
ee4c9cd6d9 | |
|
|
0c2acda3c6 | |
|
|
3d17f139c3 | |
|
|
3830e59b69 | |
|
|
498c0b970e | |
|
|
b634eb0162 | |
|
|
3d6a4d39f3 | |
|
|
e42fece1c6 | |
|
|
7ff1786ab3 | |
|
|
4843f6b60d | |
|
|
611046e649 | |
|
|
70f0d35cdb | |
|
|
a4ff6a667a | |
|
|
fb86b0ffe9 | |
|
|
a60d211a15 | |
|
|
554a890fce | |
|
|
d42aeec894 | |
|
|
3cdabcadd7 | |
|
|
bbef78ccd7 | |
|
|
94269b86e5 | |
|
|
9b5c16b7da | |
|
|
94aaeba4ad | |
|
|
d8285db06f | |
|
|
aec1b23df7 | |
|
|
77309f0b77 | |
|
|
5c4ba04e2c | |
|
|
c8a6000b25 | |
|
|
36d8602e8f | |
|
|
4f9658ecbf | |
|
|
050f4439d5 | |
|
|
6c39765788 | |
|
|
ca8581bb9a | |
|
|
3486f990c1 | |
|
|
9399fcb511 | |
|
|
af4ca742c0 | |
|
|
c27a031dcc | |
|
|
b6c8200015 | |
|
|
c11573e493 |
|
|
@ -63,3 +63,6 @@ fastlane/report.xml
|
||||||
fastlane/Preview.html
|
fastlane/Preview.html
|
||||||
fastlane/screenshots
|
fastlane/screenshots
|
||||||
fastlane/test_output
|
fastlane/test_output
|
||||||
|
|
||||||
|
# Touch Instinct custom
|
||||||
|
Downloads/
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
4.0
|
5.0
|
||||||
|
|
|
||||||
61
CHANGELOG.md
61
CHANGELOG.md
|
|
@ -1,5 +1,65 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
### 0.4.0
|
||||||
|
|
||||||
|
- **Update**: update libraries to build with Xcode 13.1
|
||||||
|
|
||||||
|
### 0.3.15
|
||||||
|
- **Update**: update LeadKit dependency
|
||||||
|
|
||||||
|
### 0.3.14
|
||||||
|
- **Update**: remove Carthage binary dependencies, update build scripts.
|
||||||
|
|
||||||
|
### 0.3.13
|
||||||
|
- **[Breaking change]**: `LabelTableViewCell` moved to `LeadKit`.
|
||||||
|
- **[Breaking change]**: Removed `PinLayout` dependency.
|
||||||
|
|
||||||
|
### 0.3.12
|
||||||
|
- **Update**: Swift 5 support
|
||||||
|
|
||||||
|
### 0.3.11
|
||||||
|
- **Add**: Carthage support.
|
||||||
|
- **[Breaking change]**: Remove `BaseDateFormatter`. Use `NumberFormattingService` from LeadKit instead.
|
||||||
|
|
||||||
|
### 0.3.10
|
||||||
|
|
||||||
|
- **[Breaking change]**: Remove `isTouchIdSupported` and `isFaceIdSupported`.
|
||||||
|
- **Add** BiometryType for BiometricsService: `touchID`, `faceID`, `none`.
|
||||||
|
|
||||||
|
### 0.3.9
|
||||||
|
|
||||||
|
- **Add**: `allowableReuseDuration` variable to `BiometricsService` which is a wrapper for touchIDAuthenticationAllowableReuseDuration.
|
||||||
|
- **Add**: individual `isTouchIdSupported` variable to `BiometricsService` to indicate if TouchId can be used.
|
||||||
|
- **Add**: `clear` function to `BiometricsService` so the context can be refreshed.
|
||||||
|
- **Update**: Documentations.
|
||||||
|
|
||||||
|
### 0.3.8
|
||||||
|
|
||||||
|
- **Fixed**: `SwiftValidator` fork moved to TouchInstinct repo, the used one is removed. Version number is downgraded to `4.0.2` to avoid collision when the original pod will update.
|
||||||
|
- **Fixed**: Extensions target building. Removed all PassCode logic, SeparatorTableViewCell and PinLayoutTableViewCell from extensions target.
|
||||||
|
|
||||||
|
### 0.3.7
|
||||||
|
|
||||||
|
- **Fixed**: `PassCodeError.tooManyAttempts` logic in `.create` and `.change` `PassCodeOperationType`
|
||||||
|
|
||||||
|
### 0.3.6
|
||||||
|
|
||||||
|
- **Update**: PassCodeError, now emmit `tooManyAttempts` in any operation (*create* / *change* / *enter*) type.
|
||||||
|
- **Update**: Rename `PassCodeControllerType` to `PassCodeOperationType`.
|
||||||
|
- **Update**: `showBiometricsRequestIfNeeded` method become public.
|
||||||
|
|
||||||
|
### 0.3.5
|
||||||
|
|
||||||
|
- **Update**: Migrate to Swift 4.2 & Xcode 10. Update dependencies.
|
||||||
|
|
||||||
|
### 0.3.4
|
||||||
|
|
||||||
|
- **Add**: `isFaceIdSupported` variable to `BiometricsService` to distinguish FaceID from TouchID.
|
||||||
|
|
||||||
|
### 0.3.3
|
||||||
|
|
||||||
|
- **Add**: Public `init` to `BiometricsService`
|
||||||
|
|
||||||
### 0.3.2
|
### 0.3.2
|
||||||
|
|
||||||
- **Add**: functions to `BasePassCodeViewController` to make `fakeTextField` become and resign first responder
|
- **Add**: functions to `BasePassCodeViewController` to make `fakeTextField` become and resign first responder
|
||||||
|
|
@ -82,4 +142,3 @@
|
||||||
## 0.1.0
|
## 0.1.0
|
||||||
|
|
||||||
- **Add**: support for Swift 3.2 / 4
|
- **Add**: support for Swift 3.2 / 4
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
github "krzyzanowskim/CryptoSwift"
|
||||||
|
github "TouchInstinct/LeadKit"
|
||||||
|
github "petropavel13/SwiftValidator"
|
||||||
|
github "kishikawakatsumi/KeychainAccess"
|
||||||
|
github "layoutBox/PinLayout"
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
github "Alamofire/Alamofire" "4.9.1"
|
||||||
|
github "ReactiveX/RxSwift" "4.5.0"
|
||||||
|
github "RxSwiftCommunity/RxAlamofire" "4.5.0"
|
||||||
|
github "SnapKit/SnapKit" "4.2.0"
|
||||||
|
github "TouchInstinct/LeadKit" "0.9.29"
|
||||||
|
github "TouchInstinct/TableKit" "2.10008.1"
|
||||||
|
github "krzyzanowskim/CryptoSwift" "1.3.0"
|
||||||
|
github "malcommac/SwiftDate" "6.1.0"
|
||||||
|
github "petropavel13/SwiftValidator" "be856202cd70e6549ebc8c9d07ec47bbff784b07"
|
||||||
|
github "pronebird/UIScrollView-InfiniteScroll" "1.1.0"
|
||||||
|
github "kishikawakatsumi/KeychainAccess" "v3.2.0"
|
||||||
|
github "layoutBox/PinLayout" "1.8.6"
|
||||||
|
|
@ -1,43 +1,21 @@
|
||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = "LeadKitAdditions"
|
s.name = "LeadKitAdditions"
|
||||||
s.version = "0.3.2"
|
s.version = "0.4.0"
|
||||||
s.summary = "iOS framework with a bunch of tools for rapid development"
|
s.summary = "iOS framework with a bunch of tools for rapid development"
|
||||||
s.homepage = "https://github.com/TouchInstinct/LeadKitAdditions"
|
s.homepage = "https://github.com/TouchInstinct/LeadKitAdditions"
|
||||||
s.license = "Apache License, Version 2.0"
|
s.license = "Apache License, Version 2.0"
|
||||||
s.author = "Touch Instinct"
|
s.author = "Touch Instinct"
|
||||||
s.platform = :ios, "9.0"
|
s.platform = :ios, "10.0"
|
||||||
s.source = { :git => "https://github.com/TouchInstinct/LeadKitAdditions.git", :tag => s.version }
|
s.source = { :git => "https://github.com/TouchInstinct/LeadKitAdditions.git", :tag => s.version }
|
||||||
|
|
||||||
s.subspec 'Core' do |ss|
|
s.subspec 'Core' do |ss|
|
||||||
ss.ios.deployment_target = '9.0'
|
ss.ios.deployment_target = '10.0'
|
||||||
ss.source_files = "Sources/**/*.swift"
|
ss.source_files = "Sources/**/*.swift"
|
||||||
|
|
||||||
ss.exclude_files = [
|
ss.dependency "LeadKit", '~> 1.7.0'
|
||||||
"Sources/Services/Network/DefaultNetworkService+ActivityIndicator+Extension.swift",
|
ss.dependency "KeychainAccess", '~> 4.2.0'
|
||||||
]
|
ss.dependency "CryptoSwift", '~> 1.4.0'
|
||||||
|
ss.dependency "SwiftValidator", '4.0.2'
|
||||||
ss.dependency "LeadKit", '~> 0.8.0'
|
|
||||||
ss.dependency "KeychainAccess", '3.1.0'
|
|
||||||
ss.dependency "CryptoSwift", '~> 0.9.0'
|
|
||||||
ss.dependency "SwiftValidator", '5.0.0'
|
|
||||||
ss.dependency "PinLayout", '~> 1.6'
|
|
||||||
end
|
|
||||||
|
|
||||||
s.subspec 'Core-iOS-Extension' do |ss|
|
|
||||||
ss.platform = :ios, '9.0'
|
|
||||||
ss.source_files = "Sources/**/*.swift"
|
|
||||||
|
|
||||||
ss.exclude_files = [
|
|
||||||
"Sources/Classes/Cells/LabelTableViewCell/*.swift",
|
|
||||||
"Sources/Services/Network/DefaultNetworkService+ActivityIndicator.swift",
|
|
||||||
"Sources/Extensions/Cells/**/*.swift"
|
|
||||||
]
|
|
||||||
|
|
||||||
ss.dependency "LeadKit/Core-iOS-Extension", '~> 0.8.0'
|
|
||||||
ss.dependency "KeychainAccess", '3.1.0'
|
|
||||||
ss.dependency "CryptoSwift", '~> 0.9.0'
|
|
||||||
ss.dependency "SwiftValidator", '5.0.0'
|
|
||||||
ss.dependency "PinLayout", '~> 1.6'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
s.default_subspec = 'Core'
|
s.default_subspec = 'Core'
|
||||||
|
|
|
||||||
|
|
@ -7,91 +7,70 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
248389A288C0A6D7914F0546 /* Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0ED4A1B793EAA73C9E95969F /* Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework */; };
|
14E3AD49502B3D81264560DB /* Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3EDEF7F6C22BB04CBB754C14 /* Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework */; };
|
||||||
3622F5D620E15DD1009DED94 /* PinLayoutTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67CF05AF206E99DF009A2AB9 /* PinLayoutTableViewCell.swift */; };
|
|
||||||
3622F5D720E15DD5009DED94 /* SeparatorTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67C2A41520724BBA000A5682 /* SeparatorTableViewCell.swift */; };
|
|
||||||
6760AF1A207268EC00C2BB7E /* PinLayoutCell+DefaultImplementation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6760AF19207268EC00C2BB7E /* PinLayoutCell+DefaultImplementation.swift */; };
|
|
||||||
67779CBC206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67779CBB206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift */; };
|
67779CBC206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67779CBB206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift */; };
|
||||||
67779CBD206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67779CBB206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift */; };
|
|
||||||
678D26AA206935B900B05B93 /* BiometricsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 678D26A9206935B900B05B93 /* BiometricsService.swift */; };
|
678D26AA206935B900B05B93 /* BiometricsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 678D26A9206935B900B05B93 /* BiometricsService.swift */; };
|
||||||
67B4E6EB206941CE00E233EA /* BiometricsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 678D26A9206935B900B05B93 /* BiometricsService.swift */; };
|
|
||||||
67B4E6F3206945D200E233EA /* BaseTextFieldViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B4E6F1206945D200E233EA /* BaseTextFieldViewModel.swift */; };
|
|
||||||
67B4E6F6206945DD00E233EA /* OnlineValidationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B4E6F5206945DC00E233EA /* OnlineValidationResult.swift */; };
|
67B4E6F6206945DD00E233EA /* OnlineValidationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B4E6F5206945DC00E233EA /* OnlineValidationResult.swift */; };
|
||||||
67B4E6F7206945DD00E233EA /* OnlineValidationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B4E6F5206945DC00E233EA /* OnlineValidationResult.swift */; };
|
|
||||||
67B4E6F9206945F900E233EA /* OnlineValidationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B4E6F8206945F900E233EA /* OnlineValidationState.swift */; };
|
67B4E6F9206945F900E233EA /* OnlineValidationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B4E6F8206945F900E233EA /* OnlineValidationState.swift */; };
|
||||||
67B4E6FA206945F900E233EA /* OnlineValidationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B4E6F8206945F900E233EA /* OnlineValidationState.swift */; };
|
|
||||||
67B4E6FB20694A4200E233EA /* BaseTextFieldViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B4E6F1206945D200E233EA /* BaseTextFieldViewModel.swift */; };
|
67B4E6FB20694A4200E233EA /* BaseTextFieldViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B4E6F1206945D200E233EA /* BaseTextFieldViewModel.swift */; };
|
||||||
67C2A41620724BBA000A5682 /* SeparatorTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67C2A41520724BBA000A5682 /* SeparatorTableViewCell.swift */; };
|
67D6041821627600002DAF5B /* LegacyConfigurableController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67D6041721627600002DAF5B /* LegacyConfigurableController.swift */; };
|
||||||
67C2A41820724EA0000A5682 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67C2A41720724EA0000A5682 /* LabelTableViewCell.swift */; };
|
786CBB2F220DD7A70017587F /* RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 786CBB22220DD7A70017587F /* RxSwift.framework */; };
|
||||||
67C2A41B20724F40000A5682 /* LabelCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67C2A41A20724F40000A5682 /* LabelCellViewModel.swift */; };
|
786CBB30220DD7A70017587F /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 786CBB23220DD7A70017587F /* Alamofire.framework */; };
|
||||||
67C2A41D20725359000A5682 /* LabelTableViewCell+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67C2A41C20725359000A5682 /* LabelTableViewCell+Extensions.swift */; };
|
786CBB31220DD7A70017587F /* TableKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 786CBB24220DD7A70017587F /* TableKit.framework */; };
|
||||||
67CF05AA206E9880009A2AB9 /* PinLayoutCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67CF05A9206E9880009A2AB9 /* PinLayoutCell.swift */; };
|
786CBB32220DD7A70017587F /* LeadKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 786CBB25220DD7A70017587F /* LeadKit.framework */; };
|
||||||
67CF05B0206E99DF009A2AB9 /* PinLayoutTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67CF05AF206E99DF009A2AB9 /* PinLayoutTableViewCell.swift */; };
|
786CBB33220DD7A70017587F /* SwiftValidator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 786CBB26220DD7A70017587F /* SwiftValidator.framework */; };
|
||||||
|
786CBB34220DD7A70017587F /* UIScrollView_InfiniteScroll.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 786CBB27220DD7A70017587F /* UIScrollView_InfiniteScroll.framework */; };
|
||||||
|
786CBB36220DD7A70017587F /* RxAlamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 786CBB29220DD7A70017587F /* RxAlamofire.framework */; };
|
||||||
|
786CBB37220DD7A70017587F /* SwiftDate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 786CBB2A220DD7A70017587F /* SwiftDate.framework */; };
|
||||||
|
786CBB38220DD7A70017587F /* RxCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 786CBB2B220DD7A70017587F /* RxCocoa.framework */; };
|
||||||
|
786CBB39220DD7A70017587F /* CryptoSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 786CBB2C220DD7A70017587F /* CryptoSwift.framework */; };
|
||||||
|
786CBB3A220DD7A70017587F /* KeychainAccess.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 786CBB2D220DD7A70017587F /* KeychainAccess.framework */; };
|
||||||
A6CFB8D91F5024A500A42CC2 /* Error+NetworkingExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6CFB8D81F5024A500A42CC2 /* Error+NetworkingExtensions.swift */; };
|
A6CFB8D91F5024A500A42CC2 /* Error+NetworkingExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6CFB8D81F5024A500A42CC2 /* Error+NetworkingExtensions.swift */; };
|
||||||
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, ); }; };
|
CAE698E81E968820000394B0 /* LeadKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = CAE698E61E968820000394B0 /* LeadKitAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
ED0C34051F2906EC00FAE9FD /* BaseDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33D41F2906EC00FAE9FD /* BaseDateFormatter.swift */; };
|
|
||||||
ED0C34061F2906EC00FAE9FD /* BaseDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33D41F2906EC00FAE9FD /* BaseDateFormatter.swift */; };
|
|
||||||
ED0C34071F2906EC00FAE9FD /* LoadingBarButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33D51F2906EC00FAE9FD /* LoadingBarButton.swift */; };
|
ED0C34071F2906EC00FAE9FD /* LoadingBarButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33D51F2906EC00FAE9FD /* LoadingBarButton.swift */; };
|
||||||
ED0C34081F2906EC00FAE9FD /* LoadingBarButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33D51F2906EC00FAE9FD /* LoadingBarButton.swift */; };
|
|
||||||
ED0C34091F2906EC00FAE9FD /* PassCodeConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33D91F2906EC00FAE9FD /* PassCodeConfiguration.swift */; };
|
ED0C34091F2906EC00FAE9FD /* PassCodeConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33D91F2906EC00FAE9FD /* PassCodeConfiguration.swift */; };
|
||||||
ED0C340A1F2906EC00FAE9FD /* PassCodeConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33D91F2906EC00FAE9FD /* PassCodeConfiguration.swift */; };
|
|
||||||
ED0C340B1F2906EC00FAE9FD /* PassCodeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33DA1F2906EC00FAE9FD /* PassCodeError.swift */; };
|
ED0C340B1F2906EC00FAE9FD /* PassCodeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33DA1F2906EC00FAE9FD /* PassCodeError.swift */; };
|
||||||
ED0C340C1F2906EC00FAE9FD /* PassCodeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33DA1F2906EC00FAE9FD /* PassCodeError.swift */; };
|
|
||||||
ED0C340D1F2906EC00FAE9FD /* PassCodeHolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33DB1F2906EC00FAE9FD /* PassCodeHolder.swift */; };
|
ED0C340D1F2906EC00FAE9FD /* PassCodeHolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33DB1F2906EC00FAE9FD /* PassCodeHolder.swift */; };
|
||||||
ED0C340E1F2906EC00FAE9FD /* PassCodeHolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33DB1F2906EC00FAE9FD /* PassCodeHolder.swift */; };
|
|
||||||
ED0C340F1F2906EC00FAE9FD /* PassCodeHolderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33DC1F2906EC00FAE9FD /* PassCodeHolderProtocol.swift */; };
|
ED0C340F1F2906EC00FAE9FD /* PassCodeHolderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33DC1F2906EC00FAE9FD /* PassCodeHolderProtocol.swift */; };
|
||||||
ED0C34101F2906EC00FAE9FD /* PassCodeHolderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33DC1F2906EC00FAE9FD /* PassCodeHolderProtocol.swift */; };
|
|
||||||
ED0C34111F2906EC00FAE9FD /* PassCodeValidationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33DD1F2906EC00FAE9FD /* PassCodeValidationResult.swift */; };
|
ED0C34111F2906EC00FAE9FD /* PassCodeValidationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33DD1F2906EC00FAE9FD /* PassCodeValidationResult.swift */; };
|
||||||
ED0C34121F2906EC00FAE9FD /* PassCodeValidationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33DD1F2906EC00FAE9FD /* PassCodeValidationResult.swift */; };
|
|
||||||
ED0C34131F2906EC00FAE9FD /* BasePassCodeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33DF1F2906EC00FAE9FD /* BasePassCodeViewController.swift */; };
|
ED0C34131F2906EC00FAE9FD /* BasePassCodeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33DF1F2906EC00FAE9FD /* BasePassCodeViewController.swift */; };
|
||||||
ED0C34141F2906EC00FAE9FD /* BasePassCodeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33DF1F2906EC00FAE9FD /* BasePassCodeViewController.swift */; };
|
|
||||||
ED0C34151F2906EC00FAE9FD /* BasePassCodeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33E11F2906EC00FAE9FD /* BasePassCodeViewModel.swift */; };
|
ED0C34151F2906EC00FAE9FD /* BasePassCodeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33E11F2906EC00FAE9FD /* BasePassCodeViewModel.swift */; };
|
||||||
ED0C34161F2906EC00FAE9FD /* BasePassCodeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33E11F2906EC00FAE9FD /* BasePassCodeViewModel.swift */; };
|
|
||||||
ED0C341F1F2906EC00FAE9FD /* UIBarButtonItem+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33E81F2906EC00FAE9FD /* UIBarButtonItem+Extensions.swift */; };
|
ED0C341F1F2906EC00FAE9FD /* UIBarButtonItem+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33E81F2906EC00FAE9FD /* UIBarButtonItem+Extensions.swift */; };
|
||||||
ED0C34201F2906EC00FAE9FD /* UIBarButtonItem+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33E81F2906EC00FAE9FD /* UIBarButtonItem+Extensions.swift */; };
|
|
||||||
ED0C34211F2906EC00FAE9FD /* UserDefaults+UserService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33E91F2906EC00FAE9FD /* UserDefaults+UserService.swift */; };
|
ED0C34211F2906EC00FAE9FD /* UserDefaults+UserService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33E91F2906EC00FAE9FD /* UserDefaults+UserService.swift */; };
|
||||||
ED0C34221F2906EC00FAE9FD /* UserDefaults+UserService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33E91F2906EC00FAE9FD /* UserDefaults+UserService.swift */; };
|
|
||||||
ED0C342D1F2906EC00FAE9FD /* BasePassCodeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33F11F2906EC00FAE9FD /* BasePassCodeService.swift */; };
|
ED0C342D1F2906EC00FAE9FD /* BasePassCodeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33F11F2906EC00FAE9FD /* BasePassCodeService.swift */; };
|
||||||
ED0C342E1F2906EC00FAE9FD /* BasePassCodeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33F11F2906EC00FAE9FD /* BasePassCodeService.swift */; };
|
|
||||||
ED0C342F1F2906EC00FAE9FD /* BaseUserService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33F21F2906EC00FAE9FD /* BaseUserService.swift */; };
|
ED0C342F1F2906EC00FAE9FD /* BaseUserService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33F21F2906EC00FAE9FD /* BaseUserService.swift */; };
|
||||||
ED0C34301F2906EC00FAE9FD /* BaseUserService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33F21F2906EC00FAE9FD /* BaseUserService.swift */; };
|
|
||||||
ED0C343F1F2906EC00FAE9FD /* ValidationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33FC1F2906EC00FAE9FD /* ValidationError.swift */; };
|
ED0C343F1F2906EC00FAE9FD /* ValidationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33FC1F2906EC00FAE9FD /* ValidationError.swift */; };
|
||||||
ED0C34401F2906EC00FAE9FD /* ValidationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33FC1F2906EC00FAE9FD /* ValidationError.swift */; };
|
|
||||||
ED0C34411F2906EC00FAE9FD /* ValidationItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33FD1F2906EC00FAE9FD /* ValidationItem.swift */; };
|
ED0C34411F2906EC00FAE9FD /* ValidationItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33FD1F2906EC00FAE9FD /* ValidationItem.swift */; };
|
||||||
ED0C34421F2906EC00FAE9FD /* ValidationItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33FD1F2906EC00FAE9FD /* ValidationItem.swift */; };
|
|
||||||
ED0C34431F2906EC00FAE9FD /* ValidationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33FE1F2906EC00FAE9FD /* ValidationService.swift */; };
|
ED0C34431F2906EC00FAE9FD /* ValidationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33FE1F2906EC00FAE9FD /* ValidationService.swift */; };
|
||||||
ED0C34441F2906EC00FAE9FD /* ValidationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33FE1F2906EC00FAE9FD /* ValidationService.swift */; };
|
|
||||||
EF5A43B1206E7A67003CED07 /* PassCodeDelayedDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF5A43B0206E7A67003CED07 /* PassCodeDelayedDescription.swift */; };
|
EF5A43B1206E7A67003CED07 /* PassCodeDelayedDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF5A43B0206E7A67003CED07 /* PassCodeDelayedDescription.swift */; };
|
||||||
EF5A43B2206E7A67003CED07 /* PassCodeDelayedDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF5A43B0206E7A67003CED07 /* PassCodeDelayedDescription.swift */; };
|
|
||||||
EFBD55921EBB9A980062AA63 /* LeadKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = CAE698E61E968820000394B0 /* LeadKitAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* 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 = "<group>"; };
|
1AC235099AA10D83D608A253 /* Pods-LeadKitAdditions-LeadKitAdditions iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeadKitAdditions-LeadKitAdditions iOS.release.xcconfig"; path = "Target Support Files/Pods-LeadKitAdditions-LeadKitAdditions iOS/Pods-LeadKitAdditions-LeadKitAdditions iOS.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
0ED4A1B793EAA73C9E95969F /* Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
3EDEF7F6C22BB04CBB754C14 /* 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 = "<group>"; };
|
|
||||||
67528BCE206E3CC6009F2525 /* iOS.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = iOS.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
67528BCE206E3CC6009F2525 /* iOS.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = iOS.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||||
6760AF19207268EC00C2BB7E /* PinLayoutCell+DefaultImplementation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PinLayoutCell+DefaultImplementation.swift"; sourceTree = "<group>"; };
|
|
||||||
67779CBB206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BaseTextFieldViewEvents+Extensions.swift"; sourceTree = "<group>"; };
|
67779CBB206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BaseTextFieldViewEvents+Extensions.swift"; sourceTree = "<group>"; };
|
||||||
678D26A9206935B900B05B93 /* BiometricsService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BiometricsService.swift; sourceTree = "<group>"; };
|
678D26A9206935B900B05B93 /* BiometricsService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BiometricsService.swift; sourceTree = "<group>"; };
|
||||||
67B4E6F1206945D200E233EA /* BaseTextFieldViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseTextFieldViewModel.swift; sourceTree = "<group>"; };
|
67B4E6F1206945D200E233EA /* BaseTextFieldViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseTextFieldViewModel.swift; sourceTree = "<group>"; };
|
||||||
67B4E6F5206945DC00E233EA /* OnlineValidationResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnlineValidationResult.swift; sourceTree = "<group>"; };
|
67B4E6F5206945DC00E233EA /* OnlineValidationResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnlineValidationResult.swift; sourceTree = "<group>"; };
|
||||||
67B4E6F8206945F900E233EA /* OnlineValidationState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnlineValidationState.swift; sourceTree = "<group>"; };
|
67B4E6F8206945F900E233EA /* OnlineValidationState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnlineValidationState.swift; sourceTree = "<group>"; };
|
||||||
67C2A41520724BBA000A5682 /* SeparatorTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorTableViewCell.swift; sourceTree = "<group>"; };
|
67D6041721627600002DAF5B /* LegacyConfigurableController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyConfigurableController.swift; sourceTree = "<group>"; };
|
||||||
67C2A41720724EA0000A5682 /* LabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelTableViewCell.swift; sourceTree = "<group>"; };
|
6FEE03727D0B955F00DE8429 /* Pods-LeadKitAdditions-LeadKitAdditions iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeadKitAdditions-LeadKitAdditions iOS.debug.xcconfig"; path = "Target Support Files/Pods-LeadKitAdditions-LeadKitAdditions iOS/Pods-LeadKitAdditions-LeadKitAdditions iOS.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
67C2A41A20724F40000A5682 /* LabelCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelCellViewModel.swift; sourceTree = "<group>"; };
|
786CBB22220DD7A70017587F /* RxSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxSwift.framework; path = Carthage/Build/iOS/RxSwift.framework; sourceTree = "<group>"; };
|
||||||
67C2A41C20725359000A5682 /* LabelTableViewCell+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LabelTableViewCell+Extensions.swift"; sourceTree = "<group>"; };
|
786CBB23220DD7A70017587F /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = Carthage/Build/iOS/Alamofire.framework; sourceTree = "<group>"; };
|
||||||
67CF05A9206E9880009A2AB9 /* PinLayoutCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinLayoutCell.swift; sourceTree = "<group>"; };
|
786CBB24220DD7A70017587F /* TableKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TableKit.framework; path = Carthage/Build/iOS/TableKit.framework; sourceTree = "<group>"; };
|
||||||
67CF05AF206E99DF009A2AB9 /* PinLayoutTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinLayoutTableViewCell.swift; sourceTree = "<group>"; };
|
786CBB25220DD7A70017587F /* LeadKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LeadKit.framework; path = Carthage/Build/iOS/LeadKit.framework; sourceTree = "<group>"; };
|
||||||
7B7F57C5E5275C4D8DC71992 /* Pods_LeadKitAdditions.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKitAdditions.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
786CBB26220DD7A70017587F /* SwiftValidator.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftValidator.framework; path = Carthage/Build/iOS/SwiftValidator.framework; sourceTree = "<group>"; };
|
||||||
9D549FA5A7579702358E07DF /* Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions.debug.xcconfig"; path = "Pods/Target Support Files/Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions/Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions.debug.xcconfig"; sourceTree = "<group>"; };
|
786CBB27220DD7A70017587F /* UIScrollView_InfiniteScroll.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIScrollView_InfiniteScroll.framework; path = Carthage/Build/iOS/UIScrollView_InfiniteScroll.framework; sourceTree = "<group>"; };
|
||||||
|
786CBB29220DD7A70017587F /* RxAlamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxAlamofire.framework; path = Carthage/Build/iOS/RxAlamofire.framework; sourceTree = "<group>"; };
|
||||||
|
786CBB2A220DD7A70017587F /* SwiftDate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftDate.framework; path = Carthage/Build/iOS/SwiftDate.framework; sourceTree = "<group>"; };
|
||||||
|
786CBB2B220DD7A70017587F /* RxCocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxCocoa.framework; path = Carthage/Build/iOS/RxCocoa.framework; sourceTree = "<group>"; };
|
||||||
|
786CBB2C220DD7A70017587F /* CryptoSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CryptoSwift.framework; path = Carthage/Build/iOS/CryptoSwift.framework; sourceTree = "<group>"; };
|
||||||
|
786CBB2D220DD7A70017587F /* KeychainAccess.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = KeychainAccess.framework; path = Carthage/Build/iOS/KeychainAccess.framework; sourceTree = "<group>"; };
|
||||||
|
786CBB2E220DD7A70017587F /* PinLayout.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PinLayout.framework; path = Carthage/Build/iOS/PinLayout.framework; sourceTree = "<group>"; };
|
||||||
A6CFB8D81F5024A500A42CC2 /* Error+NetworkingExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Error+NetworkingExtensions.swift"; sourceTree = "<group>"; };
|
A6CFB8D81F5024A500A42CC2 /* Error+NetworkingExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Error+NetworkingExtensions.swift"; sourceTree = "<group>"; };
|
||||||
CAE698E31E968820000394B0 /* LeadKitAdditions.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LeadKitAdditions.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
CAE698E31E968820000394B0 /* LeadKitAdditions.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LeadKitAdditions.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
CAE698E61E968820000394B0 /* LeadKitAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LeadKitAdditions.h; sourceTree = "<group>"; };
|
CAE698E61E968820000394B0 /* LeadKitAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LeadKitAdditions.h; sourceTree = "<group>"; };
|
||||||
CFD5627139CAB27705F75C07 /* Pods_LeadKitAdditions_LeadKitAdditions_iOS_Extensions.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKitAdditions_LeadKitAdditions_iOS_Extensions.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
D0AB283D10B2175EFDBF7924 /* Pods-LeadKitAdditions-LeadKitAdditions iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeadKitAdditions-LeadKitAdditions iOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-LeadKitAdditions-LeadKitAdditions iOS/Pods-LeadKitAdditions-LeadKitAdditions iOS.release.xcconfig"; sourceTree = "<group>"; };
|
|
||||||
ED0C33D41F2906EC00FAE9FD /* BaseDateFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseDateFormatter.swift; sourceTree = "<group>"; };
|
|
||||||
ED0C33D51F2906EC00FAE9FD /* LoadingBarButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadingBarButton.swift; sourceTree = "<group>"; };
|
ED0C33D51F2906EC00FAE9FD /* LoadingBarButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadingBarButton.swift; sourceTree = "<group>"; };
|
||||||
ED0C33D91F2906EC00FAE9FD /* PassCodeConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PassCodeConfiguration.swift; sourceTree = "<group>"; };
|
ED0C33D91F2906EC00FAE9FD /* PassCodeConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PassCodeConfiguration.swift; sourceTree = "<group>"; };
|
||||||
ED0C33DA1F2906EC00FAE9FD /* PassCodeError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PassCodeError.swift; sourceTree = "<group>"; };
|
ED0C33DA1F2906EC00FAE9FD /* PassCodeError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PassCodeError.swift; sourceTree = "<group>"; };
|
||||||
|
|
@ -108,7 +87,6 @@
|
||||||
ED0C33FD1F2906EC00FAE9FD /* ValidationItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidationItem.swift; sourceTree = "<group>"; };
|
ED0C33FD1F2906EC00FAE9FD /* ValidationItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidationItem.swift; sourceTree = "<group>"; };
|
||||||
ED0C33FE1F2906EC00FAE9FD /* ValidationService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidationService.swift; sourceTree = "<group>"; };
|
ED0C33FE1F2906EC00FAE9FD /* ValidationService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidationService.swift; sourceTree = "<group>"; };
|
||||||
EF5A43B0206E7A67003CED07 /* PassCodeDelayedDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassCodeDelayedDescription.swift; sourceTree = "<group>"; };
|
EF5A43B0206E7A67003CED07 /* PassCodeDelayedDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassCodeDelayedDescription.swift; sourceTree = "<group>"; };
|
||||||
EFBD55701EBB87100062AA63 /* LeadKitAdditions.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LeadKitAdditions.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
EFBD55781EBB893F0062AA63 /* Info-iOS-Extensions.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iOS-Extensions.plist"; sourceTree = "<group>"; };
|
EFBD55781EBB893F0062AA63 /* Info-iOS-Extensions.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iOS-Extensions.plist"; sourceTree = "<group>"; };
|
||||||
EFBD55791EBB893F0062AA63 /* Info-iOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = "<group>"; };
|
EFBD55791EBB893F0062AA63 /* Info-iOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
@ -118,31 +96,24 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
248389A288C0A6D7914F0546 /* Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework in Frameworks */,
|
786CBB2F220DD7A70017587F /* RxSwift.framework in Frameworks */,
|
||||||
);
|
786CBB30220DD7A70017587F /* Alamofire.framework in Frameworks */,
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
786CBB31220DD7A70017587F /* TableKit.framework in Frameworks */,
|
||||||
};
|
786CBB32220DD7A70017587F /* LeadKit.framework in Frameworks */,
|
||||||
EFBD556C1EBB87100062AA63 /* Frameworks */ = {
|
786CBB33220DD7A70017587F /* SwiftValidator.framework in Frameworks */,
|
||||||
isa = PBXFrameworksBuildPhase;
|
786CBB34220DD7A70017587F /* UIScrollView_InfiniteScroll.framework in Frameworks */,
|
||||||
buildActionMask = 2147483647;
|
786CBB36220DD7A70017587F /* RxAlamofire.framework in Frameworks */,
|
||||||
files = (
|
786CBB37220DD7A70017587F /* SwiftDate.framework in Frameworks */,
|
||||||
B326804BA6CC8B8BB136A46A /* Pods_LeadKitAdditions_LeadKitAdditions_iOS_Extensions.framework in Frameworks */,
|
786CBB38220DD7A70017587F /* RxCocoa.framework in Frameworks */,
|
||||||
|
786CBB39220DD7A70017587F /* CryptoSwift.framework in Frameworks */,
|
||||||
|
786CBB3A220DD7A70017587F /* KeychainAccess.framework in Frameworks */,
|
||||||
|
14E3AD49502B3D81264560DB /* Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
67528BCB206E3C12009F2525 /* Cells */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
67C2A41920724F32000A5682 /* LabelTableViewCell */,
|
|
||||||
67CF05AF206E99DF009A2AB9 /* PinLayoutTableViewCell.swift */,
|
|
||||||
67C2A41520724BBA000A5682 /* SeparatorTableViewCell.swift */,
|
|
||||||
);
|
|
||||||
path = Cells;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
67B4E6F0206945D200E233EA /* BaseTextFieldViewModel */ = {
|
67B4E6F0206945D200E233EA /* BaseTextFieldViewModel */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
|
@ -159,38 +130,22 @@
|
||||||
path = ValidationService;
|
path = ValidationService;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
67C2A41920724F32000A5682 /* LabelTableViewCell */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
67C2A41720724EA0000A5682 /* LabelTableViewCell.swift */,
|
|
||||||
67C2A41A20724F40000A5682 /* LabelCellViewModel.swift */,
|
|
||||||
);
|
|
||||||
path = LabelTableViewCell;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
67CF05A8206E986A009A2AB9 /* Cells */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
67CF05A9206E9880009A2AB9 /* PinLayoutCell.swift */,
|
|
||||||
);
|
|
||||||
path = Cells;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
67CF05AC206E9931009A2AB9 /* Cells */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
67C2A41C20725359000A5682 /* LabelTableViewCell+Extensions.swift */,
|
|
||||||
6760AF19207268EC00C2BB7E /* PinLayoutCell+DefaultImplementation.swift */,
|
|
||||||
);
|
|
||||||
path = Cells;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
A3117951840B8B7D2E7A8A80 /* Frameworks */ = {
|
A3117951840B8B7D2E7A8A80 /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
7B7F57C5E5275C4D8DC71992 /* Pods_LeadKitAdditions.framework */,
|
786CBB23220DD7A70017587F /* Alamofire.framework */,
|
||||||
0ED4A1B793EAA73C9E95969F /* Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework */,
|
786CBB2C220DD7A70017587F /* CryptoSwift.framework */,
|
||||||
CFD5627139CAB27705F75C07 /* Pods_LeadKitAdditions_LeadKitAdditions_iOS_Extensions.framework */,
|
786CBB2D220DD7A70017587F /* KeychainAccess.framework */,
|
||||||
|
786CBB25220DD7A70017587F /* LeadKit.framework */,
|
||||||
|
786CBB2E220DD7A70017587F /* PinLayout.framework */,
|
||||||
|
786CBB29220DD7A70017587F /* RxAlamofire.framework */,
|
||||||
|
786CBB2B220DD7A70017587F /* RxCocoa.framework */,
|
||||||
|
786CBB22220DD7A70017587F /* RxSwift.framework */,
|
||||||
|
786CBB2A220DD7A70017587F /* SwiftDate.framework */,
|
||||||
|
786CBB26220DD7A70017587F /* SwiftValidator.framework */,
|
||||||
|
786CBB24220DD7A70017587F /* TableKit.framework */,
|
||||||
|
786CBB27220DD7A70017587F /* UIScrollView_InfiniteScroll.framework */,
|
||||||
|
3EDEF7F6C22BB04CBB754C14 /* Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -199,10 +154,10 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
A3117951840B8B7D2E7A8A80 /* Frameworks */,
|
A3117951840B8B7D2E7A8A80 /* Frameworks */,
|
||||||
F8A65FEC7C0EB4B93746E50F /* Pods */,
|
|
||||||
CAE698E41E968820000394B0 /* Products */,
|
CAE698E41E968820000394B0 /* Products */,
|
||||||
CAE698E51E968820000394B0 /* Sources */,
|
CAE698E51E968820000394B0 /* Sources */,
|
||||||
67528BCE206E3CC6009F2525 /* iOS.playground */,
|
67528BCE206E3CC6009F2525 /* iOS.playground */,
|
||||||
|
FBC34E01DAB566B85ED77BAD /* Pods */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
|
@ -210,7 +165,6 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
CAE698E31E968820000394B0 /* LeadKitAdditions.framework */,
|
CAE698E31E968820000394B0 /* LeadKitAdditions.framework */,
|
||||||
EFBD55701EBB87100062AA63 /* LeadKitAdditions.framework */,
|
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -233,9 +187,7 @@
|
||||||
ED0C33D21F2906EC00FAE9FD /* Classes */ = {
|
ED0C33D21F2906EC00FAE9FD /* Classes */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
67528BCB206E3C12009F2525 /* Cells */,
|
|
||||||
67B4E6F0206945D200E233EA /* BaseTextFieldViewModel */,
|
67B4E6F0206945D200E233EA /* BaseTextFieldViewModel */,
|
||||||
ED0C33D41F2906EC00FAE9FD /* BaseDateFormatter.swift */,
|
|
||||||
ED0C33D51F2906EC00FAE9FD /* LoadingBarButton.swift */,
|
ED0C33D51F2906EC00FAE9FD /* LoadingBarButton.swift */,
|
||||||
);
|
);
|
||||||
path = Classes;
|
path = Classes;
|
||||||
|
|
@ -291,7 +243,6 @@
|
||||||
ED0C33E61F2906EC00FAE9FD /* Extensions */ = {
|
ED0C33E61F2906EC00FAE9FD /* Extensions */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
67CF05AC206E9931009A2AB9 /* Cells */,
|
|
||||||
ED0C33E81F2906EC00FAE9FD /* UIBarButtonItem+Extensions.swift */,
|
ED0C33E81F2906EC00FAE9FD /* UIBarButtonItem+Extensions.swift */,
|
||||||
ED0C33E91F2906EC00FAE9FD /* UserDefaults+UserService.swift */,
|
ED0C33E91F2906EC00FAE9FD /* UserDefaults+UserService.swift */,
|
||||||
A6CFB8D81F5024A500A42CC2 /* Error+NetworkingExtensions.swift */,
|
A6CFB8D81F5024A500A42CC2 /* Error+NetworkingExtensions.swift */,
|
||||||
|
|
@ -303,8 +254,8 @@
|
||||||
ED0C33EA1F2906EC00FAE9FD /* Protocols */ = {
|
ED0C33EA1F2906EC00FAE9FD /* Protocols */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
67CF05A8206E986A009A2AB9 /* Cells */,
|
|
||||||
67B4E6F4206945DC00E233EA /* ValidationService */,
|
67B4E6F4206945DC00E233EA /* ValidationService */,
|
||||||
|
67D6041721627600002DAF5B /* LegacyConfigurableController.swift */,
|
||||||
);
|
);
|
||||||
path = Protocols;
|
path = Protocols;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -331,15 +282,13 @@
|
||||||
path = ValidationService;
|
path = ValidationService;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
F8A65FEC7C0EB4B93746E50F /* Pods */ = {
|
FBC34E01DAB566B85ED77BAD /* Pods */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
49738551AC648B0AFA74E57F /* Pods-LeadKitAdditions-LeadKitAdditions iOS.debug.xcconfig */,
|
6FEE03727D0B955F00DE8429 /* Pods-LeadKitAdditions-LeadKitAdditions iOS.debug.xcconfig */,
|
||||||
D0AB283D10B2175EFDBF7924 /* Pods-LeadKitAdditions-LeadKitAdditions iOS.release.xcconfig */,
|
1AC235099AA10D83D608A253 /* Pods-LeadKitAdditions-LeadKitAdditions iOS.release.xcconfig */,
|
||||||
9D549FA5A7579702358E07DF /* Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions.debug.xcconfig */,
|
|
||||||
01605ECA03749D49C27FA3DD /* Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions.release.xcconfig */,
|
|
||||||
);
|
);
|
||||||
name = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
@ -353,14 +302,6 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
EFBD556D1EBB87100062AA63 /* Headers */ = {
|
|
||||||
isa = PBXHeadersBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
EFBD55921EBB9A980062AA63 /* LeadKitAdditions.h in Headers */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXHeadersBuildPhase section */
|
/* End PBXHeadersBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
|
|
@ -368,12 +309,11 @@
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = CAE698EB1E968820000394B0 /* Build configuration list for PBXNativeTarget "LeadKitAdditions iOS" */;
|
buildConfigurationList = CAE698EB1E968820000394B0 /* Build configuration list for PBXNativeTarget "LeadKitAdditions iOS" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
E8E82E34792B38EF225575D7 /* [CP] Check Pods Manifest.lock */,
|
DA96E76177E2633117FCBE55 /* [CP] Check Pods Manifest.lock */,
|
||||||
CAE698DE1E968820000394B0 /* Sources */,
|
CAE698DE1E968820000394B0 /* Sources */,
|
||||||
CAE698DF1E968820000394B0 /* Frameworks */,
|
CAE698DF1E968820000394B0 /* Frameworks */,
|
||||||
CAE698E01E968820000394B0 /* Headers */,
|
CAE698E01E968820000394B0 /* Headers */,
|
||||||
CAE698E11E968820000394B0 /* Resources */,
|
CAE698E11E968820000394B0 /* Resources */,
|
||||||
94F6E1BA5AD68C6E2F10062B /* [CP] Copy Pods Resources */,
|
|
||||||
CAE6990A1E969A7A000394B0 /* Swiftlint */,
|
CAE6990A1E969A7A000394B0 /* Swiftlint */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
|
|
@ -385,53 +325,29 @@
|
||||||
productReference = CAE698E31E968820000394B0 /* LeadKitAdditions.framework */;
|
productReference = CAE698E31E968820000394B0 /* LeadKitAdditions.framework */;
|
||||||
productType = "com.apple.product-type.framework";
|
productType = "com.apple.product-type.framework";
|
||||||
};
|
};
|
||||||
EFBD556F1EBB87100062AA63 /* LeadKitAdditions iOS Extensions */ = {
|
|
||||||
isa = PBXNativeTarget;
|
|
||||||
buildConfigurationList = EFBD55751EBB87100062AA63 /* Build configuration list for PBXNativeTarget "LeadKitAdditions iOS Extensions" */;
|
|
||||||
buildPhases = (
|
|
||||||
1C200FD9213D2207669C4304 /* [CP] Check Pods Manifest.lock */,
|
|
||||||
EFBD556B1EBB87100062AA63 /* Sources */,
|
|
||||||
EFBD556C1EBB87100062AA63 /* Frameworks */,
|
|
||||||
EFBD556D1EBB87100062AA63 /* Headers */,
|
|
||||||
EFBD556E1EBB87100062AA63 /* Resources */,
|
|
||||||
808FF5474C0E1574D405EFAF /* [CP] Copy Pods Resources */,
|
|
||||||
ED69E7E91F2AD0E000C74895 /* Swiftlint */,
|
|
||||||
);
|
|
||||||
buildRules = (
|
|
||||||
);
|
|
||||||
dependencies = (
|
|
||||||
);
|
|
||||||
name = "LeadKitAdditions iOS Extensions";
|
|
||||||
productName = "LeadKitAdditions-iOS-Extensions";
|
|
||||||
productReference = EFBD55701EBB87100062AA63 /* LeadKitAdditions.framework */;
|
|
||||||
productType = "com.apple.product-type.framework";
|
|
||||||
};
|
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
/* Begin PBXProject section */
|
||||||
CAE698DA1E968820000394B0 /* Project object */ = {
|
CAE698DA1E968820000394B0 /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 0930;
|
LastUpgradeCheck = 1020;
|
||||||
ORGANIZATIONNAME = TouchInstinct;
|
ORGANIZATIONNAME = TouchInstinct;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
CAE698E21E968820000394B0 = {
|
CAE698E21E968820000394B0 = {
|
||||||
CreatedOnToolsVersion = 8.3;
|
CreatedOnToolsVersion = 8.3;
|
||||||
LastSwiftMigration = 0900;
|
LastSwiftMigration = 1020;
|
||||||
ProvisioningStyle = Manual;
|
|
||||||
};
|
|
||||||
EFBD556F1EBB87100062AA63 = {
|
|
||||||
CreatedOnToolsVersion = 8.3.1;
|
|
||||||
ProvisioningStyle = Manual;
|
ProvisioningStyle = Manual;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = CAE698DD1E968820000394B0 /* Build configuration list for PBXProject "LeadKitAdditions" */;
|
buildConfigurationList = CAE698DD1E968820000394B0 /* Build configuration list for PBXProject "LeadKitAdditions" */;
|
||||||
compatibilityVersion = "Xcode 3.2";
|
compatibilityVersion = "Xcode 3.2";
|
||||||
developmentRegion = English;
|
developmentRegion = en;
|
||||||
hasScannedForEncodings = 0;
|
hasScannedForEncodings = 0;
|
||||||
knownRegions = (
|
knownRegions = (
|
||||||
en,
|
en,
|
||||||
|
Base,
|
||||||
);
|
);
|
||||||
mainGroup = CAE698D91E968820000394B0;
|
mainGroup = CAE698D91E968820000394B0;
|
||||||
productRefGroup = CAE698E41E968820000394B0 /* Products */;
|
productRefGroup = CAE698E41E968820000394B0 /* Products */;
|
||||||
|
|
@ -439,7 +355,6 @@
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
CAE698E21E968820000394B0 /* LeadKitAdditions iOS */,
|
CAE698E21E968820000394B0 /* LeadKitAdditions iOS */,
|
||||||
EFBD556F1EBB87100062AA63 /* LeadKitAdditions iOS Extensions */,
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
@ -452,64 +367,9 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
EFBD556E1EBB87100062AA63 /* Resources */ = {
|
|
||||||
isa = PBXResourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
1C200FD9213D2207669C4304 /* [CP] Check Pods Manifest.lock */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
|
||||||
"${PODS_ROOT}/Manifest.lock",
|
|
||||||
);
|
|
||||||
name = "[CP] Check Pods Manifest.lock";
|
|
||||||
outputPaths = (
|
|
||||||
"$(DERIVED_FILE_DIR)/Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions-checkManifestLockResult.txt",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
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# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
808FF5474C0E1574D405EFAF /* [CP] Copy Pods Resources */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "[CP] Copy Pods Resources";
|
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions/Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions-resources.sh\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
94F6E1BA5AD68C6E2F10062B /* [CP] Copy Pods Resources */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "[CP] Copy Pods Resources";
|
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-LeadKitAdditions-LeadKitAdditions iOS/Pods-LeadKitAdditions-LeadKitAdditions iOS-resources.sh\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
CAE6990A1E969A7A000394B0 /* Swiftlint */ = {
|
CAE6990A1E969A7A000394B0 /* Swiftlint */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
|
@ -522,18 +382,22 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = ". build-scripts/xcode/build_phases/swiftlint.sh Sources";
|
shellScript = ". run_swiftlint.sh\n";
|
||||||
};
|
};
|
||||||
E8E82E34792B38EF225575D7 /* [CP] Check Pods Manifest.lock */ = {
|
DA96E76177E2633117FCBE55 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
"${PODS_ROOT}/Manifest.lock",
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
);
|
);
|
||||||
name = "[CP] Check Pods Manifest.lock";
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
"$(DERIVED_FILE_DIR)/Pods-LeadKitAdditions-LeadKitAdditions iOS-checkManifestLockResult.txt",
|
"$(DERIVED_FILE_DIR)/Pods-LeadKitAdditions-LeadKitAdditions iOS-checkManifestLockResult.txt",
|
||||||
);
|
);
|
||||||
|
|
@ -542,20 +406,6 @@
|
||||||
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# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
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# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
ED69E7E91F2AD0E000C74895 /* Swiftlint */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = Swiftlint;
|
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = ". build-scripts/xcode/build_phases/swiftlint.sh Sources";
|
|
||||||
};
|
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
|
@ -563,70 +413,32 @@
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
67D6041821627600002DAF5B /* LegacyConfigurableController.swift in Sources */,
|
||||||
67B4E6FB20694A4200E233EA /* BaseTextFieldViewModel.swift in Sources */,
|
67B4E6FB20694A4200E233EA /* BaseTextFieldViewModel.swift in Sources */,
|
||||||
ED0C340F1F2906EC00FAE9FD /* PassCodeHolderProtocol.swift in Sources */,
|
ED0C340F1F2906EC00FAE9FD /* PassCodeHolderProtocol.swift in Sources */,
|
||||||
ED0C343F1F2906EC00FAE9FD /* ValidationError.swift in Sources */,
|
ED0C343F1F2906EC00FAE9FD /* ValidationError.swift in Sources */,
|
||||||
ED0C342F1F2906EC00FAE9FD /* BaseUserService.swift in Sources */,
|
ED0C342F1F2906EC00FAE9FD /* BaseUserService.swift in Sources */,
|
||||||
678D26AA206935B900B05B93 /* BiometricsService.swift in Sources */,
|
678D26AA206935B900B05B93 /* BiometricsService.swift in Sources */,
|
||||||
67C2A41D20725359000A5682 /* LabelTableViewCell+Extensions.swift in Sources */,
|
|
||||||
ED0C34411F2906EC00FAE9FD /* ValidationItem.swift in Sources */,
|
ED0C34411F2906EC00FAE9FD /* ValidationItem.swift in Sources */,
|
||||||
ED0C341F1F2906EC00FAE9FD /* UIBarButtonItem+Extensions.swift in Sources */,
|
ED0C341F1F2906EC00FAE9FD /* UIBarButtonItem+Extensions.swift in Sources */,
|
||||||
67C2A41820724EA0000A5682 /* LabelTableViewCell.swift in Sources */,
|
|
||||||
ED0C34091F2906EC00FAE9FD /* PassCodeConfiguration.swift in Sources */,
|
ED0C34091F2906EC00FAE9FD /* PassCodeConfiguration.swift in Sources */,
|
||||||
EF5A43B1206E7A67003CED07 /* PassCodeDelayedDescription.swift in Sources */,
|
EF5A43B1206E7A67003CED07 /* PassCodeDelayedDescription.swift in Sources */,
|
||||||
67CF05B0206E99DF009A2AB9 /* PinLayoutTableViewCell.swift in Sources */,
|
|
||||||
ED0C34131F2906EC00FAE9FD /* BasePassCodeViewController.swift in Sources */,
|
ED0C34131F2906EC00FAE9FD /* BasePassCodeViewController.swift in Sources */,
|
||||||
67C2A41620724BBA000A5682 /* SeparatorTableViewCell.swift in Sources */,
|
|
||||||
ED0C342D1F2906EC00FAE9FD /* BasePassCodeService.swift in Sources */,
|
ED0C342D1F2906EC00FAE9FD /* BasePassCodeService.swift in Sources */,
|
||||||
67B4E6F9206945F900E233EA /* OnlineValidationState.swift in Sources */,
|
67B4E6F9206945F900E233EA /* OnlineValidationState.swift in Sources */,
|
||||||
67779CBC206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift in Sources */,
|
67779CBC206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift in Sources */,
|
||||||
ED0C340D1F2906EC00FAE9FD /* PassCodeHolder.swift in Sources */,
|
ED0C340D1F2906EC00FAE9FD /* PassCodeHolder.swift in Sources */,
|
||||||
67CF05AA206E9880009A2AB9 /* PinLayoutCell.swift in Sources */,
|
|
||||||
A6CFB8D91F5024A500A42CC2 /* Error+NetworkingExtensions.swift in Sources */,
|
A6CFB8D91F5024A500A42CC2 /* Error+NetworkingExtensions.swift in Sources */,
|
||||||
ED0C34071F2906EC00FAE9FD /* LoadingBarButton.swift in Sources */,
|
ED0C34071F2906EC00FAE9FD /* LoadingBarButton.swift in Sources */,
|
||||||
6760AF1A207268EC00C2BB7E /* PinLayoutCell+DefaultImplementation.swift in Sources */,
|
|
||||||
ED0C34211F2906EC00FAE9FD /* UserDefaults+UserService.swift in Sources */,
|
ED0C34211F2906EC00FAE9FD /* UserDefaults+UserService.swift in Sources */,
|
||||||
ED0C34111F2906EC00FAE9FD /* PassCodeValidationResult.swift in Sources */,
|
ED0C34111F2906EC00FAE9FD /* PassCodeValidationResult.swift in Sources */,
|
||||||
ED0C34051F2906EC00FAE9FD /* BaseDateFormatter.swift in Sources */,
|
|
||||||
ED0C34431F2906EC00FAE9FD /* ValidationService.swift in Sources */,
|
ED0C34431F2906EC00FAE9FD /* ValidationService.swift in Sources */,
|
||||||
ED0C340B1F2906EC00FAE9FD /* PassCodeError.swift in Sources */,
|
ED0C340B1F2906EC00FAE9FD /* PassCodeError.swift in Sources */,
|
||||||
67B4E6F6206945DD00E233EA /* OnlineValidationResult.swift in Sources */,
|
67B4E6F6206945DD00E233EA /* OnlineValidationResult.swift in Sources */,
|
||||||
67C2A41B20724F40000A5682 /* LabelCellViewModel.swift in Sources */,
|
|
||||||
ED0C34151F2906EC00FAE9FD /* BasePassCodeViewModel.swift in Sources */,
|
ED0C34151F2906EC00FAE9FD /* BasePassCodeViewModel.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
EFBD556B1EBB87100062AA63 /* Sources */ = {
|
|
||||||
isa = PBXSourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
67779CBD206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift in Sources */,
|
|
||||||
ED0C34101F2906EC00FAE9FD /* PassCodeHolderProtocol.swift in Sources */,
|
|
||||||
ED0C34401F2906EC00FAE9FD /* ValidationError.swift in Sources */,
|
|
||||||
3622F5D720E15DD5009DED94 /* SeparatorTableViewCell.swift in Sources */,
|
|
||||||
ED0C34301F2906EC00FAE9FD /* BaseUserService.swift in Sources */,
|
|
||||||
ED0C34421F2906EC00FAE9FD /* ValidationItem.swift in Sources */,
|
|
||||||
ED0C34201F2906EC00FAE9FD /* UIBarButtonItem+Extensions.swift in Sources */,
|
|
||||||
ED0C340A1F2906EC00FAE9FD /* PassCodeConfiguration.swift in Sources */,
|
|
||||||
67B4E6FA206945F900E233EA /* OnlineValidationState.swift in Sources */,
|
|
||||||
67B4E6EB206941CE00E233EA /* BiometricsService.swift in Sources */,
|
|
||||||
ED0C34141F2906EC00FAE9FD /* BasePassCodeViewController.swift in Sources */,
|
|
||||||
ED0C342E1F2906EC00FAE9FD /* BasePassCodeService.swift in Sources */,
|
|
||||||
67B4E6F7206945DD00E233EA /* OnlineValidationResult.swift in Sources */,
|
|
||||||
ED0C340E1F2906EC00FAE9FD /* PassCodeHolder.swift in Sources */,
|
|
||||||
67B4E6F3206945D200E233EA /* BaseTextFieldViewModel.swift in Sources */,
|
|
||||||
ED0C34081F2906EC00FAE9FD /* LoadingBarButton.swift in Sources */,
|
|
||||||
ED0C34221F2906EC00FAE9FD /* UserDefaults+UserService.swift in Sources */,
|
|
||||||
ED0C34121F2906EC00FAE9FD /* PassCodeValidationResult.swift in Sources */,
|
|
||||||
ED0C34061F2906EC00FAE9FD /* BaseDateFormatter.swift in Sources */,
|
|
||||||
3622F5D620E15DD1009DED94 /* PinLayoutTableViewCell.swift in Sources */,
|
|
||||||
ED0C34441F2906EC00FAE9FD /* ValidationService.swift in Sources */,
|
|
||||||
EF5A43B2206E7A67003CED07 /* PassCodeDelayedDescription.swift in Sources */,
|
|
||||||
ED0C340C1F2906EC00FAE9FD /* PassCodeError.swift in Sources */,
|
|
||||||
ED0C34161F2906EC00FAE9FD /* BasePassCodeViewModel.swift in Sources */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
|
|
@ -634,6 +446,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
|
@ -696,6 +509,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
|
@ -749,9 +563,9 @@
|
||||||
};
|
};
|
||||||
CAE698EC1E968820000394B0 /* Debug */ = {
|
CAE698EC1E968820000394B0 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 49738551AC648B0AFA74E57F /* Pods-LeadKitAdditions-LeadKitAdditions iOS.debug.xcconfig */;
|
baseConfigurationReference = 6FEE03727D0B955F00DE8429 /* Pods-LeadKitAdditions-LeadKitAdditions iOS.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_IDENTITY = "";
|
CODE_SIGN_IDENTITY = "";
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
|
|
@ -761,22 +575,22 @@
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
INFOPLIST_FILE = "$(SRCROOT)/Sources/Info-iOS.plist";
|
INFOPLIST_FILE = "$(SRCROOT)/Sources/Info-iOS.plist";
|
||||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "touchinstinct.LeadKitAdditions-iOS";
|
PRODUCT_BUNDLE_IDENTIFIER = "touchinstinct.LeadKitAdditions-iOS";
|
||||||
PRODUCT_NAME = LeadKitAdditions;
|
PRODUCT_NAME = LeadKitAdditions;
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 4.0;
|
SWIFT_VERSION = 5.0;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
CAE698ED1E968820000394B0 /* Release */ = {
|
CAE698ED1E968820000394B0 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = D0AB283D10B2175EFDBF7924 /* Pods-LeadKitAdditions-LeadKitAdditions iOS.release.xcconfig */;
|
baseConfigurationReference = 1AC235099AA10D83D608A253 /* Pods-LeadKitAdditions-LeadKitAdditions iOS.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_IDENTITY = "";
|
CODE_SIGN_IDENTITY = "";
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
|
|
@ -786,61 +600,13 @@
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
INFOPLIST_FILE = "$(SRCROOT)/Sources/Info-iOS.plist";
|
INFOPLIST_FILE = "$(SRCROOT)/Sources/Info-iOS.plist";
|
||||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "touchinstinct.LeadKitAdditions-iOS";
|
PRODUCT_BUNDLE_IDENTIFIER = "touchinstinct.LeadKitAdditions-iOS";
|
||||||
PRODUCT_NAME = LeadKitAdditions;
|
PRODUCT_NAME = LeadKitAdditions;
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
SWIFT_VERSION = 4.0;
|
SWIFT_VERSION = 5.0;
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
EFBD55761EBB87100062AA63 /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = 9D549FA5A7579702358E07DF /* Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions.debug.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
|
||||||
CODE_SIGN_IDENTITY = "";
|
|
||||||
DEFINES_MODULE = YES;
|
|
||||||
DEVELOPMENT_TEAM = "";
|
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
|
||||||
DYLIB_CURRENT_VERSION = 1;
|
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
|
||||||
INFOPLIST_FILE = "$(SRCROOT)/Sources/Info-iOS-Extensions.plist";
|
|
||||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "touchinstinct.LeadKitAdditions-iOS-Extensions";
|
|
||||||
PRODUCT_NAME = LeadKitAdditions;
|
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
|
||||||
SKIP_INSTALL = YES;
|
|
||||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
|
||||||
SWIFT_VERSION = 4.0;
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
EFBD55771EBB87100062AA63 /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = 01605ECA03749D49C27FA3DD /* Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions.release.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
|
||||||
CODE_SIGN_IDENTITY = "";
|
|
||||||
DEFINES_MODULE = YES;
|
|
||||||
DEVELOPMENT_TEAM = "";
|
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
|
||||||
DYLIB_CURRENT_VERSION = 1;
|
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
|
||||||
INFOPLIST_FILE = "$(SRCROOT)/Sources/Info-iOS-Extensions.plist";
|
|
||||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "touchinstinct.LeadKitAdditions-iOS-Extensions";
|
|
||||||
PRODUCT_NAME = LeadKitAdditions;
|
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
|
||||||
SKIP_INSTALL = YES;
|
|
||||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
|
|
||||||
SWIFT_VERSION = 4.0;
|
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
|
@ -865,15 +631,6 @@
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
EFBD55751EBB87100062AA63 /* Build configuration list for PBXNativeTarget "LeadKitAdditions iOS Extensions" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
EFBD55761EBB87100062AA63 /* Debug */,
|
|
||||||
EFBD55771EBB87100062AA63 /* Release */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
};
|
};
|
||||||
rootObject = CAE698DA1E968820000394B0 /* Project object */;
|
rootObject = CAE698DA1E968820000394B0 /* Project object */;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1020"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "CAE698E21E968820000394B0"
|
||||||
|
BuildableName = "LeadKitAdditions.framework"
|
||||||
|
BlueprintName = "LeadKitAdditions iOS"
|
||||||
|
ReferencedContainer = "container:LeadKitAdditions.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "CAE698E21E968820000394B0"
|
||||||
|
BuildableName = "LeadKitAdditions.framework"
|
||||||
|
BlueprintName = "LeadKitAdditions iOS"
|
||||||
|
ReferencedContainer = "container:LeadKitAdditions.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "CAE698E21E968820000394B0"
|
||||||
|
BuildableName = "LeadKitAdditions.framework"
|
||||||
|
BlueprintName = "LeadKitAdditions iOS"
|
||||||
|
ReferencedContainer = "container:LeadKitAdditions.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
25
Podfile
25
Podfile
|
|
@ -1,29 +1,20 @@
|
||||||
source "https://github.com/CocoaPods/Specs.git"
|
source 'https://cdn.cocoapods.org/'
|
||||||
source "https://github.com/TouchInstinct/Podspecs.git"
|
source "https://github.com/TouchInstinct/Podspecs.git"
|
||||||
|
|
||||||
abstract_target 'LeadKitAdditions' do
|
abstract_target 'LeadKitAdditions' do
|
||||||
pod "KeychainAccess", '3.1.0'
|
pod "KeychainAccess", '~> 4.2.0'
|
||||||
pod "CryptoSwift", "~> 0.9.0"
|
pod "CryptoSwift", "~> 1.4.0"
|
||||||
pod "SwiftValidator", '5.0.0'
|
pod "SwiftValidator", '4.0.2'
|
||||||
pod "SwiftLint", '~> 0.25'
|
pod "SwiftLint", '~> 0.45.0'
|
||||||
pod "PinLayout", '~> 1.6'
|
pod "PinLayout", '~> 1.6'
|
||||||
|
|
||||||
inhibit_all_warnings!
|
inhibit_all_warnings!
|
||||||
|
use_frameworks!
|
||||||
|
|
||||||
target 'LeadKitAdditions iOS' do
|
target 'LeadKitAdditions iOS' do
|
||||||
platform :ios, '9.0'
|
platform :ios, '10.0'
|
||||||
|
|
||||||
use_frameworks!
|
pod 'LeadKit', '~> 1.7.0'
|
||||||
|
|
||||||
pod 'LeadKit', '~> 0.7.0'
|
|
||||||
end
|
|
||||||
|
|
||||||
target 'LeadKitAdditions iOS Extensions' do
|
|
||||||
platform :ios, '9.0'
|
|
||||||
|
|
||||||
use_frameworks!
|
|
||||||
|
|
||||||
pod "LeadKit/Core-iOS-Extension", '~> 0.7.0'
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
129
Podfile.lock
129
Podfile.lock
|
|
@ -1,64 +1,81 @@
|
||||||
PODS:
|
PODS:
|
||||||
- Alamofire (4.7.2)
|
- Alamofire (5.5.0)
|
||||||
- CryptoSwift (0.9.0)
|
- CryptoSwift (1.4.2)
|
||||||
- KeychainAccess (3.1.0)
|
- KeychainAccess (4.2.2)
|
||||||
- LeadKit (0.7.12):
|
- LeadKit (1.7.0):
|
||||||
- LeadKit/Core (= 0.7.12)
|
- LeadKit/Core (= 1.7.0)
|
||||||
- LeadKit/Core (0.7.12):
|
- LeadKit/Core (1.7.0):
|
||||||
- ObjectMapper (~> 3.1)
|
- RxAlamofire (~> 6.1)
|
||||||
- RxAlamofire (~> 4.1)
|
- RxCocoa (~> 6.2)
|
||||||
- RxCocoa (~> 4.1)
|
- RxSwift (~> 6.2)
|
||||||
- RxSwift (~> 4.1)
|
- SnapKit (~> 5.0.1)
|
||||||
- SwiftDate (~> 4.5)
|
- SwiftDate (~> 6)
|
||||||
- TableKit (~> 2.6)
|
- TableKit (~> 2.11)
|
||||||
- UIScrollView-InfiniteScroll (~> 1.0.0)
|
- UIScrollView-InfiniteScroll (~> 1.1.0)
|
||||||
- LeadKit/Core-iOS-Extension (0.7.12):
|
- PinLayout (1.8.6)
|
||||||
- ObjectMapper (~> 3.1)
|
- RxAlamofire (6.1.1):
|
||||||
- RxAlamofire (~> 4.1)
|
- RxAlamofire/Core (= 6.1.1)
|
||||||
- RxCocoa (~> 4.1)
|
- RxAlamofire/Core (6.1.1):
|
||||||
- RxSwift (~> 4.1)
|
- Alamofire (~> 5.4)
|
||||||
- SwiftDate (~> 4.5)
|
- RxSwift (~> 6.0)
|
||||||
- ObjectMapper (3.1.0)
|
- RxCocoa (6.2.0):
|
||||||
- PinLayout (1.6.0)
|
- RxRelay (= 6.2.0)
|
||||||
- RxAlamofire (4.2.0):
|
- RxSwift (= 6.2.0)
|
||||||
- RxAlamofire/Core (= 4.2.0)
|
- RxRelay (6.2.0):
|
||||||
- RxAlamofire/Core (4.2.0):
|
- RxSwift (= 6.2.0)
|
||||||
- Alamofire (~> 4.5)
|
- RxSwift (6.2.0)
|
||||||
- RxSwift (~> 4)
|
- SnapKit (5.0.1)
|
||||||
- RxCocoa (4.1.2):
|
- SwiftDate (6.3.1)
|
||||||
- RxSwift (~> 4.0)
|
- SwiftLint (0.45.1)
|
||||||
- RxSwift (4.1.2)
|
- SwiftValidator (4.0.2)
|
||||||
- SwiftDate (4.5.1)
|
- TableKit (2.11.0)
|
||||||
- SwiftLint (0.25.1)
|
- UIScrollView-InfiniteScroll (1.1.0)
|
||||||
- SwiftValidator (5.0.0)
|
|
||||||
- TableKit (2.6.0)
|
|
||||||
- UIScrollView-InfiniteScroll (1.0.2)
|
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- CryptoSwift (~> 0.9.0)
|
- CryptoSwift (~> 1.4.0)
|
||||||
- KeychainAccess (= 3.1.0)
|
- KeychainAccess (~> 4.2.0)
|
||||||
- LeadKit (~> 0.7.0)
|
- LeadKit (~> 1.7.0)
|
||||||
- LeadKit/Core-iOS-Extension (~> 0.7.0)
|
|
||||||
- PinLayout (~> 1.6)
|
- PinLayout (~> 1.6)
|
||||||
- SwiftLint (~> 0.25)
|
- SwiftLint (~> 0.45.0)
|
||||||
- SwiftValidator (= 5.0.0)
|
- SwiftValidator (= 4.0.2)
|
||||||
|
|
||||||
|
SPEC REPOS:
|
||||||
|
https://github.com/CocoaPods/Specs.git:
|
||||||
|
- PinLayout
|
||||||
|
https://github.com/TouchInstinct/Podspecs.git:
|
||||||
|
- LeadKit
|
||||||
|
- SwiftValidator
|
||||||
|
trunk:
|
||||||
|
- Alamofire
|
||||||
|
- CryptoSwift
|
||||||
|
- KeychainAccess
|
||||||
|
- RxAlamofire
|
||||||
|
- RxCocoa
|
||||||
|
- RxRelay
|
||||||
|
- RxSwift
|
||||||
|
- SnapKit
|
||||||
|
- SwiftDate
|
||||||
|
- SwiftLint
|
||||||
|
- TableKit
|
||||||
|
- UIScrollView-InfiniteScroll
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Alamofire: e4fa87002c137ba2d8d634d2c51fabcda0d5c223
|
Alamofire: 1c4fb5369c3fe93d2857c780d8bbe09f06f97e7c
|
||||||
CryptoSwift: bca8c5b653dcc2d9734409242a070ff53bafac86
|
CryptoSwift: a532e74ed010f8c95f611d00b8bbae42e9fe7c17
|
||||||
KeychainAccess: 94c5540b32eabf7bc32bfb976a268e8ea05fd6da
|
KeychainAccess: c0c4f7f38f6fc7bbe58f5702e25f7bd2f65abf51
|
||||||
LeadKit: e6628cfa16f5bab6fc001d4fcba9608f60fb6fd3
|
LeadKit: e5765a6edac2813042304e940fd7a43b37be80ca
|
||||||
ObjectMapper: 20505058f54e5c3ca69e1d6de9897d152a5369a6
|
PinLayout: fe2a2432d6982588e208572005c941aeeae417ab
|
||||||
PinLayout: a2bbe9057d49a1e326b13dc4fe8c14751f8c8844
|
RxAlamofire: beb75a1c452d0de225651db4903f5d29d034a620
|
||||||
RxAlamofire: 87a9c588541210cc3e4a1f843ccc3ecf3eb98b31
|
RxCocoa: 4baf94bb35f2c0ab31bc0cb9f1900155f646ba42
|
||||||
RxCocoa: d88ba0f1f6abf040011a9eb4b539324fc426843a
|
RxRelay: e72dbfd157807478401ef1982e1c61c945c94b2f
|
||||||
RxSwift: e49536837d9901277638493ea537394d4b55f570
|
RxSwift: d356ab7bee873611322f134c5f9ef379fa183d8f
|
||||||
SwiftDate: 7b56d42a221f582047287deb256b23fc5ed49a60
|
SnapKit: 97b92857e3df3a0c71833cce143274bf6ef8e5eb
|
||||||
SwiftLint: ce933681be10c3266e82576dad676fa815a602e9
|
SwiftDate: 72d28954e8e1c6c1c0f917ccc8005e4f83c7d4b2
|
||||||
SwiftValidator: 46cdd2061962df3ee8bab3c536dea9b34191d459
|
SwiftLint: 06ac37e4d38c7068e0935bb30cda95f093bec761
|
||||||
TableKit: 61880e4c13ac0ba396a308fcb1ae48f6dec8b458
|
SwiftValidator: 8517a67bceebd7286cb487da259db7dd44c5fc74
|
||||||
UIScrollView-InfiniteScroll: c132d6d5851daff229ab4a1060ccf70a05a051c9
|
TableKit: 8a1a267d841a2da638ea09bdb0db33aedb459fa8
|
||||||
|
UIScrollView-InfiniteScroll: 3ef456bcbe759c19f510a383cff96e6647c98c98
|
||||||
|
|
||||||
PODFILE CHECKSUM: 18dadbe1461045569b8c35d705ed56bcac3325c6
|
PODFILE CHECKSUM: 1d0f91b670998d56b8cf9bc24d5b265a89e8409b
|
||||||
|
|
||||||
COCOAPODS: 1.4.0
|
COCOAPODS: 1.10.1
|
||||||
|
|
|
||||||
|
|
@ -1,107 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Touch Instinct
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the Software), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
// THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
/// Base date formatter class, contains most frequently used formats, including RFC3339
|
|
||||||
open class BaseDateFormatter {
|
|
||||||
|
|
||||||
private static let apiDateTimeFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
|
|
||||||
private static let apiDateWithoutTimeFormat = "yyyy-MM-dd'T'Z"
|
|
||||||
private static let hourAndMinuteDateTimeFormat = "HH:mm"
|
|
||||||
private static let dayAndMonthDateTimeFormat = "dd MMM"
|
|
||||||
private static let dayMonthYearDateTimeFormat = "dd.MM.yyyy"
|
|
||||||
|
|
||||||
private static let apiFormatter: DateFormatter = {
|
|
||||||
let dateFormatter = DateFormatter()
|
|
||||||
dateFormatter.dateFormat = apiDateTimeFormat
|
|
||||||
return dateFormatter
|
|
||||||
}()
|
|
||||||
|
|
||||||
private static let apiDateWithoutTimeFormatter: DateFormatter = {
|
|
||||||
let dateFormatter = DateFormatter()
|
|
||||||
dateFormatter.dateFormat = apiDateWithoutTimeFormat
|
|
||||||
return dateFormatter
|
|
||||||
}()
|
|
||||||
|
|
||||||
private static let hourAndMinuteFormatter: DateFormatter = {
|
|
||||||
let dateFormater = DateFormatter()
|
|
||||||
dateFormater.dateFormat = hourAndMinuteDateTimeFormat
|
|
||||||
return dateFormater
|
|
||||||
}()
|
|
||||||
|
|
||||||
private static let dayAndMonthFormatter: DateFormatter = {
|
|
||||||
let dateFormater = DateFormatter()
|
|
||||||
dateFormater.dateFormat = dayAndMonthDateTimeFormat
|
|
||||||
return dateFormater
|
|
||||||
}()
|
|
||||||
|
|
||||||
private static let dayMonthYearFormatter: DateFormatter = {
|
|
||||||
let dateFormater = DateFormatter()
|
|
||||||
dateFormater.dateFormat = dayMonthYearDateTimeFormat
|
|
||||||
return dateFormater
|
|
||||||
}()
|
|
||||||
|
|
||||||
// MARK: - Public interface
|
|
||||||
|
|
||||||
/// DateFormatter's locale can be overriden
|
|
||||||
open class var usedLocale: Locale {
|
|
||||||
return .current
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse date from string with format: yyyy-MM-dd'T'HH:mm:ssZ
|
|
||||||
public static func backendDate(fromStrDate strDate: String) -> Date? {
|
|
||||||
apiFormatter.locale = usedLocale
|
|
||||||
return apiFormatter.date(from: strDate)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Serialize date into string with format: yyyy-MM-dd'T'HH:mm:ssZ
|
|
||||||
public static func backendStrDate(withDate date: Date) -> String {
|
|
||||||
apiFormatter.locale = usedLocale
|
|
||||||
return apiFormatter.string(from: date)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Serialize date into string with format: yyyy-MM-dd'T'Z
|
|
||||||
public static func backendDateWithoutTime(withDate date: Date) -> String {
|
|
||||||
apiDateWithoutTimeFormatter.locale = usedLocale
|
|
||||||
return apiDateWithoutTimeFormatter.string(from: date)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Serialize date into string with format: HH:mm
|
|
||||||
public static func hourAndMinuteStrDate(withDate date: Date) -> String {
|
|
||||||
hourAndMinuteFormatter.locale = usedLocale
|
|
||||||
return hourAndMinuteFormatter.string(from: date)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Serialize date into string with format: dd MMM
|
|
||||||
public static func dayAndMonthStrDate(withDate date: Date) -> String {
|
|
||||||
hourAndMinuteFormatter.locale = usedLocale
|
|
||||||
return dayAndMonthFormatter.string(from: date)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Serialize date into string with format: dd.MM.yyyy
|
|
||||||
public static func dayMonthYearStrDate(withDate date: Date) -> String {
|
|
||||||
hourAndMinuteFormatter.locale = usedLocale
|
|
||||||
return dayMonthYearFormatter.string(from: date)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -36,7 +36,6 @@ open class BaseTextFieldViewEvents: TextFieldViewEvents {
|
||||||
public init(textChangedDriver: Driver<String?>) {
|
public init(textChangedDriver: Driver<String?>) {
|
||||||
self.textChangedDriver = textChangedDriver
|
self.textChangedDriver = textChangedDriver
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Base implementation of text field view model events.
|
/// Base implementation of text field view model events.
|
||||||
|
|
@ -60,7 +59,6 @@ open class BaseTextFieldViewModelEvents: TextFieldViewModelEvents {
|
||||||
self.changeValidationStateDriver = changeValidationStateDriver
|
self.changeValidationStateDriver = changeValidationStateDriver
|
||||||
self.changeOnlineValidationStateDriver = changeOnlineValidationStateDriver
|
self.changeOnlineValidationStateDriver = changeOnlineValidationStateDriver
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension BaseTextFieldViewModelEvents {
|
public extension BaseTextFieldViewModelEvents {
|
||||||
|
|
@ -101,14 +99,13 @@ public extension BaseTextFieldViewModelEvents {
|
||||||
using offlineRules: [Rule] = [],
|
using offlineRules: [Rule] = [],
|
||||||
validationClosure: @escaping OnlineValidationClosure) -> Driver<OnlineValidationState> {
|
validationClosure: @escaping OnlineValidationClosure) -> Driver<OnlineValidationState> {
|
||||||
|
|
||||||
return textDriver.flatMap { string -> Driver<OnlineValidationState> in
|
textDriver.flatMap { string -> Driver<OnlineValidationState> in
|
||||||
guard let nonEmptyString = string, !nonEmptyString.isEmpty else {
|
guard let nonEmptyString = string, !nonEmptyString.isEmpty else {
|
||||||
return .just(.initial)
|
return .just(.initial)
|
||||||
}
|
}
|
||||||
|
|
||||||
let passedRules = offlineRules
|
let passedRules = offlineRules
|
||||||
.map { $0.validate(nonEmptyString) }
|
.allSatisfy { $0.validate(nonEmptyString) }
|
||||||
.reduce(true) { $0 && $1 }
|
|
||||||
|
|
||||||
guard passedRules else {
|
guard passedRules else {
|
||||||
return .just(.initial)
|
return .just(.initial)
|
||||||
|
|
@ -139,7 +136,7 @@ public extension BaseTextFieldViewModelEvents {
|
||||||
rules: [Rule] = [RequiredRule()],
|
rules: [Rule] = [RequiredRule()],
|
||||||
validationService: ValidationService,
|
validationService: ValidationService,
|
||||||
onlineValidationClosure: OnlineValidationClosure? = nil,
|
onlineValidationClosure: OnlineValidationClosure? = nil,
|
||||||
onlineValidationThrottle: RxTimeInterval = 0.5) {
|
onlineValidationThrottle: RxTimeInterval = .milliseconds(500)) {
|
||||||
|
|
||||||
let dataModelFieldDriver = binding.fieldDriver
|
let dataModelFieldDriver = binding.fieldDriver
|
||||||
|
|
||||||
|
|
@ -164,5 +161,4 @@ public extension BaseTextFieldViewModelEvents {
|
||||||
changeValidationStateDriver: offlineValidationDriver,
|
changeValidationStateDriver: offlineValidationDriver,
|
||||||
changeOnlineValidationStateDriver: onlineValidationDriver)
|
changeOnlineValidationStateDriver: onlineValidationDriver)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Touch Instinct
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the Software), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
// THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit.UIGeometry
|
|
||||||
import LeadKit
|
|
||||||
|
|
||||||
/// Default view model for LabelTableViewCell.
|
|
||||||
open class LabelCellViewModel {
|
|
||||||
|
|
||||||
public let viewText: ViewText
|
|
||||||
public let contentBackground: ViewBackground
|
|
||||||
public let contentInsets: UIEdgeInsets
|
|
||||||
public let labelInsets: UIEdgeInsets
|
|
||||||
public let separatorType: CellSeparatorType
|
|
||||||
|
|
||||||
/// Memberwise initializer.
|
|
||||||
///
|
|
||||||
/// - Parameters:
|
|
||||||
/// - viewText: View text to configure label.
|
|
||||||
/// - contentBackground: View background to configure background.
|
|
||||||
/// - contentInsets: Content insets to use for layout whole content.
|
|
||||||
/// - labelInsets: Label insets to use for layout label.
|
|
||||||
/// - separatorType: Separator type to use for separators.
|
|
||||||
public init(viewText: ViewText,
|
|
||||||
contentBackground: ViewBackground = .color(.clear),
|
|
||||||
contentInsets: UIEdgeInsets = .zero,
|
|
||||||
labelInsets: UIEdgeInsets = .zero,
|
|
||||||
separatorType: CellSeparatorType = .none) {
|
|
||||||
|
|
||||||
self.viewText = viewText
|
|
||||||
self.contentBackground = contentBackground
|
|
||||||
self.contentInsets = contentInsets
|
|
||||||
self.labelInsets = labelInsets
|
|
||||||
self.separatorType = separatorType
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,141 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Touch Instinct
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the Software), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
// THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
import LeadKit
|
|
||||||
import PinLayout
|
|
||||||
|
|
||||||
/// Pin layout cell with separators, background and label.
|
|
||||||
open class LabelTableViewCell: SeparatorTableViewCell {
|
|
||||||
|
|
||||||
private let label = UILabel(frame: .zero)
|
|
||||||
private let backgroundImageView = UIImageView(frame: .zero)
|
|
||||||
private let contentContainerView = UIView(frame: .zero)
|
|
||||||
|
|
||||||
private var viewModel: LabelCellViewModel?
|
|
||||||
|
|
||||||
// MARK: - PinLayoutTableViewCell
|
|
||||||
|
|
||||||
override open func addViews() {
|
|
||||||
super.addViews()
|
|
||||||
|
|
||||||
contentContainerView.addSubview(backgroundImageView)
|
|
||||||
contentContainerView.addSubview(label)
|
|
||||||
|
|
||||||
contentView.addSubview(contentContainerView)
|
|
||||||
}
|
|
||||||
|
|
||||||
override open func configureAppearance() {
|
|
||||||
super.configureAppearance()
|
|
||||||
|
|
||||||
selectionStyle = .none
|
|
||||||
backgroundColor = .clear
|
|
||||||
|
|
||||||
contentView.backgroundColor = .clear
|
|
||||||
|
|
||||||
configureAppearance(of: label, backgroundImageView: backgroundImageView)
|
|
||||||
}
|
|
||||||
|
|
||||||
override open func layout() {
|
|
||||||
let topSeparatorHeight = viewModel?.separatorType.topConfiguration?.totalHeight ?? 0
|
|
||||||
let bottomSeparatorHeight = viewModel?.separatorType.bottomConfiguration?.totalHeight ?? 0
|
|
||||||
|
|
||||||
contentContainerView.pin
|
|
||||||
.top(topSeparatorHeight + contentInsets.top)
|
|
||||||
.horizontally(contentInsets)
|
|
||||||
.bottom(contentInsets.bottom + bottomSeparatorHeight)
|
|
||||||
.layout()
|
|
||||||
|
|
||||||
label.pin
|
|
||||||
.top(labelInsets)
|
|
||||||
.horizontally(labelInsets)
|
|
||||||
.sizeToFit(.width)
|
|
||||||
.layout()
|
|
||||||
|
|
||||||
backgroundImageView.pin
|
|
||||||
.all()
|
|
||||||
.layout()
|
|
||||||
|
|
||||||
// bottom separator positioning after content size (height) calculation
|
|
||||||
super.layout()
|
|
||||||
}
|
|
||||||
|
|
||||||
private var labelInsets: UIEdgeInsets {
|
|
||||||
return viewModel?.labelInsets ?? .zero
|
|
||||||
}
|
|
||||||
|
|
||||||
private var contentInsets: UIEdgeInsets {
|
|
||||||
return viewModel?.contentInsets ?? .zero
|
|
||||||
}
|
|
||||||
|
|
||||||
override open var contentHeight: CGFloat {
|
|
||||||
let selfContentHeight = contentInsets.top +
|
|
||||||
labelInsets.top +
|
|
||||||
label.frame.height +
|
|
||||||
labelInsets.bottom +
|
|
||||||
contentInsets.bottom
|
|
||||||
|
|
||||||
return selfContentHeight + super.contentHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Subclass methods to override
|
|
||||||
|
|
||||||
/// Callback for label and background image view appearance configuration.
|
|
||||||
///
|
|
||||||
/// - Parameters:
|
|
||||||
/// - label: Internal UILabel instance to configure.
|
|
||||||
/// - backgroundImageView: Internal UIImageView instance to configure.
|
|
||||||
open func configureAppearance(of label: UILabel, backgroundImageView: UIImageView) {
|
|
||||||
label.numberOfLines = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Configuration methods
|
|
||||||
|
|
||||||
/// Convenient method for configuration cell with LabelCellViewModel.
|
|
||||||
///
|
|
||||||
/// - Parameter viewModel: LabelCellViewModel instance.
|
|
||||||
public func configureLabelCell(with viewModel: LabelCellViewModel) {
|
|
||||||
self.viewModel = viewModel
|
|
||||||
|
|
||||||
configureSeparator(with: viewModel.separatorType)
|
|
||||||
configureLabelText(with: viewModel.viewText)
|
|
||||||
configureContentBackground(with: viewModel.contentBackground)
|
|
||||||
|
|
||||||
setNeedsLayout()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Method for background configuration.
|
|
||||||
///
|
|
||||||
/// - Parameter contentBackground: Content background to use as background.
|
|
||||||
public func configureContentBackground(with contentBackground: ViewBackground) {
|
|
||||||
contentBackground.configure(backgroundView: contentContainerView,
|
|
||||||
backgroundImageView: backgroundImageView)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Method for text configuration.
|
|
||||||
///
|
|
||||||
/// - Parameter viewText: View text to use as background.
|
|
||||||
public func configureLabelText(with viewText: ViewText) {
|
|
||||||
label.configure(with: viewText)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Touch Instinct
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the Software), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
// THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
import PinLayout
|
|
||||||
|
|
||||||
/// Cell that uses PinLayout. Contains methods that should be overriden in subclasses.
|
|
||||||
open class PinLayoutTableViewCell: UITableViewCell, PinLayoutCell {
|
|
||||||
|
|
||||||
public override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
|
|
||||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
|
||||||
|
|
||||||
initializeCell()
|
|
||||||
}
|
|
||||||
|
|
||||||
public required init?(coder aDecoder: NSCoder) {
|
|
||||||
super.init(coder: aDecoder)
|
|
||||||
|
|
||||||
initializeCell()
|
|
||||||
}
|
|
||||||
|
|
||||||
open override func sizeThatFits(_ size: CGSize) -> CGSize {
|
|
||||||
return layout(with: size)
|
|
||||||
}
|
|
||||||
|
|
||||||
open override func layoutSubviews() {
|
|
||||||
super.layoutSubviews()
|
|
||||||
|
|
||||||
layout()
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - PinLayoutCell
|
|
||||||
|
|
||||||
open func initializeCell() {
|
|
||||||
addViews()
|
|
||||||
configureAppearance()
|
|
||||||
configureLayout()
|
|
||||||
}
|
|
||||||
|
|
||||||
open func layout(with containerSize: CGSize) -> CGSize {
|
|
||||||
// 1) Set the contentView's width to the specified size parameter
|
|
||||||
contentView.pin.width(containerSize.width).layout()
|
|
||||||
|
|
||||||
// 2) Layout the contentView's controls
|
|
||||||
layout()
|
|
||||||
|
|
||||||
// 3) Returns a size that contains all controls
|
|
||||||
return CGSize(width: contentView.frame.width,
|
|
||||||
height: contentHeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
open func addViews() {
|
|
||||||
// override in subclass
|
|
||||||
|
|
||||||
// move from _UISnapshotWindow superview in Playground
|
|
||||||
addSubview(contentView)
|
|
||||||
}
|
|
||||||
|
|
||||||
open func configureAppearance() {
|
|
||||||
// override in subclass
|
|
||||||
}
|
|
||||||
|
|
||||||
open func configureLayout() {
|
|
||||||
// override in subclass
|
|
||||||
}
|
|
||||||
|
|
||||||
open func layout() {
|
|
||||||
// override in subclass
|
|
||||||
}
|
|
||||||
|
|
||||||
open var contentHeight: CGFloat {
|
|
||||||
return contentView.subviewsMaxY
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private extension UIView {
|
|
||||||
|
|
||||||
var subviewsMaxY: CGFloat {
|
|
||||||
return subviews
|
|
||||||
.map { $0.frame.maxY }
|
|
||||||
.max() ?? frame.maxY
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Touch Instinct
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the Software), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
// THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
import LeadKit
|
|
||||||
import PinLayout
|
|
||||||
|
|
||||||
/// Pin layout cell with top and bottom separators.
|
|
||||||
open class SeparatorTableViewCell: PinLayoutTableViewCell {
|
|
||||||
|
|
||||||
private let topSeparator = UIView(frame: .zero)
|
|
||||||
private let bottomSeparator = UIView(frame: .zero)
|
|
||||||
|
|
||||||
private var separatorType: CellSeparatorType = .none
|
|
||||||
|
|
||||||
/// Configure separator with viewModel.
|
|
||||||
/// - parameter separatorType: type of separators.
|
|
||||||
public func configureSeparator(with separatorType: CellSeparatorType) {
|
|
||||||
self.separatorType = separatorType
|
|
||||||
|
|
||||||
separatorType.configure(topSeparatorView: topSeparator,
|
|
||||||
bottomSeparatorView: bottomSeparator)
|
|
||||||
|
|
||||||
setNeedsLayout()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Move separator upward in hierarchy
|
|
||||||
public func bringSeparatorsToFront() {
|
|
||||||
contentView.bringSubview(toFront: topSeparator)
|
|
||||||
contentView.bringSubview(toFront: bottomSeparator)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Move separator backward in hierarchy
|
|
||||||
public func sendSeparatorsToBack() {
|
|
||||||
contentView.sendSubview(toBack: topSeparator)
|
|
||||||
contentView.sendSubview(toBack: bottomSeparator)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - PinLayoutTableViewCell
|
|
||||||
|
|
||||||
override open func addViews() {
|
|
||||||
super.addViews()
|
|
||||||
|
|
||||||
contentView.addSubview(topSeparator)
|
|
||||||
contentView.addSubview(bottomSeparator)
|
|
||||||
}
|
|
||||||
|
|
||||||
override open func layout() {
|
|
||||||
super.layout()
|
|
||||||
|
|
||||||
if let topConfiguration = separatorType.topConfiguration {
|
|
||||||
topSeparator.pin
|
|
||||||
.top(topConfiguration.insets)
|
|
||||||
.horizontally(topConfiguration.insets)
|
|
||||||
.height(topConfiguration.height)
|
|
||||||
.layout()
|
|
||||||
}
|
|
||||||
|
|
||||||
if let bottomConfiguration = separatorType.bottomConfiguration {
|
|
||||||
let topInset = contentHeight - (bottomConfiguration.height + bottomConfiguration.insets.bottom)
|
|
||||||
|
|
||||||
bottomSeparator.pin
|
|
||||||
.top(topInset)
|
|
||||||
.horizontally(bottomConfiguration.insets)
|
|
||||||
.height(bottomConfiguration.height)
|
|
||||||
.layout()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override open var contentHeight: CGFloat {
|
|
||||||
let topSeparatorHeight = separatorType.topConfiguration?.totalHeight ?? 0
|
|
||||||
let bottomSeparatorHeight = separatorType.bottomConfiguration?.totalHeight ?? 0
|
|
||||||
|
|
||||||
return topSeparatorHeight + bottomSeparatorHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - UITableViewCell
|
|
||||||
|
|
||||||
override open func prepareForReuse() {
|
|
||||||
super.prepareForReuse()
|
|
||||||
|
|
||||||
configureSeparator(with: .none)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -42,6 +42,7 @@ public class LoadingBarButton {
|
||||||
switch side {
|
switch side {
|
||||||
case .left:
|
case .left:
|
||||||
return navigationItem?.leftBarButtonItem
|
return navigationItem?.leftBarButtonItem
|
||||||
|
|
||||||
case .right:
|
case .right:
|
||||||
return navigationItem?.rightBarButtonItem
|
return navigationItem?.rightBarButtonItem
|
||||||
}
|
}
|
||||||
|
|
@ -50,6 +51,7 @@ public class LoadingBarButton {
|
||||||
switch side {
|
switch side {
|
||||||
case .left:
|
case .left:
|
||||||
navigationItem?.leftBarButtonItem = newValue
|
navigationItem?.leftBarButtonItem = newValue
|
||||||
|
|
||||||
case .right:
|
case .right:
|
||||||
navigationItem?.rightBarButtonItem = newValue
|
navigationItem?.rightBarButtonItem = newValue
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +80,6 @@ public class LoadingBarButton {
|
||||||
barButtonItem = initialBarButton
|
barButtonItem = initialBarButton
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension Observable {
|
public extension Observable {
|
||||||
|
|
@ -92,13 +93,12 @@ public extension Observable {
|
||||||
- Returns:
|
- Returns:
|
||||||
- observable, that handles LoadingBarButton behaviour
|
- observable, that handles LoadingBarButton behaviour
|
||||||
*/
|
*/
|
||||||
func changeLoadingUI(using barButton: LoadingBarButton) -> Observable<Observable.E> {
|
func changeLoadingUI(using barButton: LoadingBarButton) -> Observable<Observable.Element> {
|
||||||
return observeOn(MainScheduler.instance)
|
observe(on: MainScheduler.instance)
|
||||||
.do(onSubscribe: {
|
.do(onSubscribe: {
|
||||||
barButton.setState(waiting: true)
|
barButton.setState(waiting: true)
|
||||||
}, onDispose: {
|
}, onDispose: {
|
||||||
barButton.setState(waiting: false)
|
barButton.setState(waiting: false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,6 @@ public struct PassCodeConfiguration {
|
||||||
|
|
||||||
/// Returns configuration with default values
|
/// Returns configuration with default values
|
||||||
public static var defaultConfiguration: PassCodeConfiguration {
|
public static var defaultConfiguration: PassCodeConfiguration {
|
||||||
return PassCodeConfiguration()
|
PassCodeConfiguration()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,5 +32,4 @@ public struct PassCodeDelayedDescription {
|
||||||
self.description = description
|
self.description = description
|
||||||
self.delay = delay
|
self.delay = delay
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,13 +21,15 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
/// Describes error, which may occur during pass code entering
|
/// Describes error, which may occur during pass code entering
|
||||||
/// - codesNotMatch: Different codes
|
|
||||||
/// - wrongCode: Value is remaining attemps
|
|
||||||
/// - tooManyAttempts: Attempts limit reached
|
|
||||||
public enum PassCodeError: Error {
|
public enum PassCodeError: Error {
|
||||||
|
/// Different codes
|
||||||
case codesNotMatch
|
case codesNotMatch
|
||||||
case wrongCode(Int)
|
|
||||||
case tooManyAttempts
|
/// Value is remaining attemps
|
||||||
|
case wrongCode(attemptsRemaining: Int)
|
||||||
|
|
||||||
|
/// Attempts limit reached (for create, change or enter)
|
||||||
|
case tooManyAttempts(type: PassCodeOperationType)
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension PassCodeError {
|
public extension PassCodeError {
|
||||||
|
|
@ -35,6 +37,7 @@ public extension PassCodeError {
|
||||||
switch self {
|
switch self {
|
||||||
case .tooManyAttempts:
|
case .tooManyAttempts:
|
||||||
return true
|
return true
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,22 +26,22 @@ import RxCocoa
|
||||||
public extension PassCodeHolderProtocol {
|
public extension PassCodeHolderProtocol {
|
||||||
|
|
||||||
var passCodeHolderCreate: PassCodeHolderCreate? {
|
var passCodeHolderCreate: PassCodeHolderCreate? {
|
||||||
return self as? PassCodeHolderCreate
|
self as? PassCodeHolderCreate
|
||||||
}
|
}
|
||||||
|
|
||||||
var passCodeHolderEnter: PassCodeHolderEnter? {
|
var passCodeHolderEnter: PassCodeHolderEnter? {
|
||||||
return self as? PassCodeHolderEnter
|
self as? PassCodeHolderEnter
|
||||||
}
|
}
|
||||||
|
|
||||||
var passCodeHolderChange: PassCodeHolderChange? {
|
var passCodeHolderChange: PassCodeHolderChange? {
|
||||||
return self as? PassCodeHolderChange
|
self as? PassCodeHolderChange
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Holds information about pass codes during pass code creation process
|
/// Holds information about pass codes during pass code creation process
|
||||||
public class PassCodeHolderCreate: PassCodeHolderProtocol {
|
public class PassCodeHolderCreate: PassCodeHolderProtocol {
|
||||||
|
|
||||||
public let type: PassCodeControllerType = .create
|
public let type: PassCodeOperationType = .create
|
||||||
|
|
||||||
private var firstPassCode: String?
|
private var firstPassCode: String?
|
||||||
private var secondPassCode: String?
|
private var secondPassCode: String?
|
||||||
|
|
@ -55,7 +55,7 @@ public class PassCodeHolderCreate: PassCodeHolderProtocol {
|
||||||
}
|
}
|
||||||
|
|
||||||
public var shouldValidate: Bool {
|
public var shouldValidate: Bool {
|
||||||
return firstPassCode != nil && secondPassCode != nil
|
firstPassCode != nil && secondPassCode != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
public var passCode: String? {
|
public var passCode: String? {
|
||||||
|
|
@ -70,8 +70,10 @@ public class PassCodeHolderCreate: PassCodeHolderProtocol {
|
||||||
switch enterStep {
|
switch enterStep {
|
||||||
case .enter:
|
case .enter:
|
||||||
firstPassCode = passCode
|
firstPassCode = passCode
|
||||||
|
|
||||||
case .repeatEnter:
|
case .repeatEnter:
|
||||||
secondPassCode = passCode
|
secondPassCode = passCode
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -89,17 +91,16 @@ public class PassCodeHolderCreate: PassCodeHolderProtocol {
|
||||||
firstPassCode = nil
|
firstPassCode = nil
|
||||||
secondPassCode = nil
|
secondPassCode = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Holds information about pass code during pass code entering process
|
/// Holds information about pass code during pass code entering process
|
||||||
public class PassCodeHolderEnter: PassCodeHolderProtocol {
|
public class PassCodeHolderEnter: PassCodeHolderProtocol {
|
||||||
|
|
||||||
public let type: PassCodeControllerType = .enter
|
public let type: PassCodeOperationType = .enter
|
||||||
public let enterStep: PassCodeControllerState = .enter
|
public let enterStep: PassCodeControllerState = .enter
|
||||||
|
|
||||||
public var shouldValidate: Bool {
|
public var shouldValidate: Bool {
|
||||||
return passCode != nil
|
passCode != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
public var passCode: String?
|
public var passCode: String?
|
||||||
|
|
@ -119,13 +120,12 @@ public class PassCodeHolderEnter: PassCodeHolderProtocol {
|
||||||
public func reset() {
|
public func reset() {
|
||||||
passCode = nil
|
passCode = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Holds information about pass codes during pass code changing process
|
/// Holds information about pass codes during pass code changing process
|
||||||
public class PassCodeHolderChange: PassCodeHolderProtocol {
|
public class PassCodeHolderChange: PassCodeHolderProtocol {
|
||||||
|
|
||||||
public let type: PassCodeControllerType = .change
|
public let type: PassCodeOperationType = .change
|
||||||
|
|
||||||
private var oldPassCode: String?
|
private var oldPassCode: String?
|
||||||
private var newFirstPassCode: String?
|
private var newFirstPassCode: String?
|
||||||
|
|
@ -153,12 +153,15 @@ public class PassCodeHolderChange: PassCodeHolderProtocol {
|
||||||
|
|
||||||
public var passCode: String? {
|
public var passCode: String? {
|
||||||
switch (oldPassCode, newFirstPassCode, newSecondPassCode) {
|
switch (oldPassCode, newFirstPassCode, newSecondPassCode) {
|
||||||
case (let oldPassCode?, nil, nil):
|
case let (oldPassCode?, nil, nil):
|
||||||
return oldPassCode
|
return oldPassCode
|
||||||
|
|
||||||
case (_, _?, nil):
|
case (_, _?, nil):
|
||||||
return nil
|
return nil
|
||||||
case (_, let newFirstPassCode?, let newSecondPassCode?) where newFirstPassCode == newSecondPassCode:
|
|
||||||
|
case let (_, newFirstPassCode?, newSecondPassCode?) where newFirstPassCode == newSecondPassCode:
|
||||||
return newFirstPassCode
|
return newFirstPassCode
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -190,5 +193,4 @@ public class PassCodeHolderChange: PassCodeHolderProtocol {
|
||||||
newSecondPassCode = nil
|
newSecondPassCode = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
public protocol PassCodeHolderProtocol {
|
public protocol PassCodeHolderProtocol {
|
||||||
|
|
||||||
/// Type of operation with pass code
|
/// Type of operation with pass code
|
||||||
var type: PassCodeControllerType { get }
|
var type: PassCodeOperationType { get }
|
||||||
/// Operation step
|
/// Operation step
|
||||||
var enterStep: PassCodeControllerState { get }
|
var enterStep: PassCodeControllerState { get }
|
||||||
|
|
||||||
|
|
@ -41,7 +41,6 @@ public protocol PassCodeHolderProtocol {
|
||||||
|
|
||||||
/// Returns passCode or error if pass code is invalid
|
/// Returns passCode or error if pass code is invalid
|
||||||
func validate() -> PassCodeValidationResult
|
func validate() -> PassCodeValidationResult
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PassCodeHolderBuilder {
|
public class PassCodeHolderBuilder {
|
||||||
|
|
@ -54,15 +53,16 @@ public class PassCodeHolderBuilder {
|
||||||
- parameter type: type of pass code controller
|
- parameter type: type of pass code controller
|
||||||
- returns: pass code information holder, specific by type
|
- returns: pass code information holder, specific by type
|
||||||
*/
|
*/
|
||||||
public static func build(with type: PassCodeControllerType) -> PassCodeHolderProtocol {
|
public static func build(with type: PassCodeOperationType) -> PassCodeHolderProtocol {
|
||||||
switch type {
|
switch type {
|
||||||
case .create:
|
case .create:
|
||||||
return PassCodeHolderCreate()
|
return PassCodeHolderCreate()
|
||||||
|
|
||||||
case .enter:
|
case .enter:
|
||||||
return PassCodeHolderEnter()
|
return PassCodeHolderEnter()
|
||||||
|
|
||||||
case .change:
|
case .change:
|
||||||
return PassCodeHolderChange()
|
return PassCodeHolderChange()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ public enum PassCodeValidationResult {
|
||||||
|
|
||||||
case valid(String)
|
case valid(String)
|
||||||
case invalid(PassCodeError?)
|
case invalid(PassCodeError?)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension PassCodeValidationResult {
|
public extension PassCodeValidationResult {
|
||||||
|
|
@ -33,6 +32,7 @@ public extension PassCodeValidationResult {
|
||||||
switch self {
|
switch self {
|
||||||
case .valid:
|
case .valid:
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case .invalid:
|
case .invalid:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -42,6 +42,7 @@ public extension PassCodeValidationResult {
|
||||||
switch self {
|
switch self {
|
||||||
case let .valid(passCode):
|
case let .valid(passCode):
|
||||||
return passCode
|
return passCode
|
||||||
|
|
||||||
case .invalid:
|
case .invalid:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -51,6 +52,7 @@ public extension PassCodeValidationResult {
|
||||||
switch self {
|
switch self {
|
||||||
case let .invalid(error):
|
case let .invalid(error):
|
||||||
return error
|
return error
|
||||||
|
|
||||||
case .valid:
|
case .valid:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ public enum PinImageType {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pass code operation type
|
/// Pass code operation type
|
||||||
public enum PassCodeControllerType {
|
public enum PassCodeOperationType {
|
||||||
case create
|
case create
|
||||||
case enter
|
case enter
|
||||||
case change
|
case change
|
||||||
|
|
@ -47,9 +47,9 @@ public enum PassCodeControllerState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Base view controller that operates with pass code
|
/// Base view controller that operates with pass code
|
||||||
open class BasePassCodeViewController: UIViewController, ConfigurableController {
|
open class BasePassCodeViewController: UIViewController, LegacyConfigurableController {
|
||||||
|
|
||||||
public var viewModel: BasePassCodeViewModel!
|
public var viewModel: BasePassCodeViewModel! // swiftlint:disable:this implicitly_unwrapped_optional
|
||||||
|
|
||||||
// MARK: - IBOutlets
|
// MARK: - IBOutlets
|
||||||
|
|
||||||
|
|
@ -100,7 +100,7 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationCenter.default.rx.notification(.UIApplicationWillResignActive)
|
NotificationCenter.default.rx.notification(UIApplication.willResignActiveNotification)
|
||||||
.subscribe(onNext: { [weak self] _ in
|
.subscribe(onNext: { [weak self] _ in
|
||||||
self?.resetUI()
|
self?.resetUI()
|
||||||
})
|
})
|
||||||
|
|
@ -150,16 +150,6 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func showBiometricsRequestIfNeeded() {
|
|
||||||
guard viewModel.isBiometricsEnabled && viewModel.controllerType == .enter else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.authenticateUsingBiometrics(with: biometricsAuthorizationHint,
|
|
||||||
fallback: biometricsFallbackButtonTitle,
|
|
||||||
cancel: biometricsCancelButtonTitle)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func resetUI() {
|
private func resetUI() {
|
||||||
resetDotsUI()
|
resetDotsUI()
|
||||||
viewModel.reset()
|
viewModel.reset()
|
||||||
|
|
@ -211,7 +201,8 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController
|
||||||
.sorted { $0.delay < $1.delay }
|
.sorted { $0.delay < $1.delay }
|
||||||
.map { [weak self] delayedDescription in
|
.map { [weak self] delayedDescription in
|
||||||
Observable<Int>
|
Observable<Int>
|
||||||
.interval(delayedDescription.delay, scheduler: MainScheduler.instance)
|
.interval(.seconds(Int(delayedDescription.delay)),
|
||||||
|
scheduler: MainScheduler.instance)
|
||||||
.take(1)
|
.take(1)
|
||||||
.do(onNext: { _ in
|
.do(onNext: { _ in
|
||||||
self?.errorLabel?.attributedText = delayedDescription.description
|
self?.errorLabel?.attributedText = delayedDescription.description
|
||||||
|
|
@ -251,6 +242,17 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController
|
||||||
fakeTextField.resignFirstResponder()
|
fakeTextField.resignFirstResponder()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Show biometrics system UI if applicable
|
||||||
|
public func showBiometricsRequestIfNeeded() {
|
||||||
|
guard viewModel.isBiometricsEnabled && viewModel.operationType == .enter else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.authenticateUsingBiometrics(with: biometricsAuthorizationHint,
|
||||||
|
fallback: biometricsFallbackButtonTitle,
|
||||||
|
cancel: biometricsCancelButtonTitle)
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - ConfigurableController
|
// MARK: - ConfigurableController
|
||||||
|
|
||||||
open func bindViews() {
|
open func bindViews() {
|
||||||
|
|
@ -259,7 +261,7 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController
|
||||||
self?.setStates(for: text ?? "")
|
self?.setStates(for: text ?? "")
|
||||||
self?.hideError()
|
self?.hideError()
|
||||||
})
|
})
|
||||||
.delay(0.1) // time to draw dots
|
.delay(.milliseconds(100)) // time to draw dots
|
||||||
.drive(onNext: { [weak self] text in
|
.drive(onNext: { [weak self] text in
|
||||||
self?.viewModel.setPassCodeText(text)
|
self?.viewModel.setPassCodeText(text)
|
||||||
})
|
})
|
||||||
|
|
@ -288,12 +290,11 @@ open class BasePassCodeViewController: UIViewController, ConfigurableController
|
||||||
|
|
||||||
open func addViews() {}
|
open func addViews() {}
|
||||||
|
|
||||||
open func setAppearance() {}
|
open func configureAppearance() {}
|
||||||
|
|
||||||
open func configureBarButtons() {}
|
open func configureBarButtons() {}
|
||||||
|
|
||||||
open func localize() {}
|
open func localize() {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - UITextFieldDelegate
|
// MARK: - UITextFieldDelegate
|
||||||
|
|
@ -307,5 +308,4 @@ extension BasePassCodeViewController: UITextFieldDelegate {
|
||||||
let invalid = CharacterSet(charactersIn: "0123456789").inverted
|
let invalid = CharacterSet(charactersIn: "0123456789").inverted
|
||||||
return string.rangeOfCharacter(from: invalid, options: [], range: string.startIndex..<string.endIndex) == nil
|
return string.rangeOfCharacter(from: invalid, options: [], range: string.startIndex..<string.endIndex) == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
//
|
//
|
||||||
|
|
||||||
import LeadKit
|
|
||||||
import RxSwift
|
import RxSwift
|
||||||
import RxCocoa
|
import RxCocoa
|
||||||
|
|
||||||
|
|
@ -31,9 +30,9 @@ public enum PassCodeAuthType {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Base view model for passCodeViewController
|
/// Base view model for passCodeViewController
|
||||||
open class BasePassCodeViewModel: BaseViewModel {
|
open class BasePassCodeViewModel {
|
||||||
|
|
||||||
public let controllerType: PassCodeControllerType
|
public let operationType: PassCodeOperationType
|
||||||
|
|
||||||
public let disposeBag = DisposeBag()
|
public let disposeBag = DisposeBag()
|
||||||
|
|
||||||
|
|
@ -43,24 +42,24 @@ open class BasePassCodeViewModel: BaseViewModel {
|
||||||
/// Contains configuration for pass code operations
|
/// Contains configuration for pass code operations
|
||||||
public let passCodeConfiguration: PassCodeConfiguration
|
public let passCodeConfiguration: PassCodeConfiguration
|
||||||
|
|
||||||
private let validationResultHolder = Variable<PassCodeValidationResult?>(nil)
|
private let validationResultHolder = BehaviorRelay<PassCodeValidationResult?>(value: nil)
|
||||||
public var validationResultDriver: Driver<PassCodeValidationResult?> {
|
public var validationResultDriver: Driver<PassCodeValidationResult?> {
|
||||||
return validationResultHolder.asDriver()
|
validationResultHolder.asDriver()
|
||||||
}
|
}
|
||||||
|
|
||||||
private let passCodeControllerStateVariable = Variable<PassCodeControllerState>(.enter)
|
private let passCodeControllerStateVariable = BehaviorRelay<PassCodeControllerState>(value: .enter)
|
||||||
public var passCodeControllerStateDriver: Driver<PassCodeControllerState> {
|
public var passCodeControllerStateDriver: Driver<PassCodeControllerState> {
|
||||||
return passCodeControllerStateVariable.asDriver()
|
passCodeControllerStateVariable.asDriver()
|
||||||
}
|
}
|
||||||
|
|
||||||
private let passCodeText = Variable<String?>(nil)
|
private let passCodeText = BehaviorRelay<String?>(value: nil)
|
||||||
|
|
||||||
private var attemptsNumber = 0
|
private var attemptsNumber = 0
|
||||||
|
|
||||||
private lazy var passCodeHolder: PassCodeHolderProtocol = PassCodeHolderBuilder.build(with: self.controllerType)
|
private lazy var passCodeHolder: PassCodeHolderProtocol = PassCodeHolderBuilder.build(with: self.operationType)
|
||||||
|
|
||||||
public init(controllerType: PassCodeControllerType, passCodeConfiguration: PassCodeConfiguration) {
|
public init(operationType: PassCodeOperationType, passCodeConfiguration: PassCodeConfiguration) {
|
||||||
self.controllerType = controllerType
|
self.operationType = operationType
|
||||||
self.passCodeConfiguration = passCodeConfiguration
|
self.passCodeConfiguration = passCodeConfiguration
|
||||||
|
|
||||||
bindViewModel()
|
bindViewModel()
|
||||||
|
|
@ -85,17 +84,17 @@ open class BasePassCodeViewModel: BaseViewModel {
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|
||||||
public var passCodeTextValue: String? {
|
public var passCodeTextValue: String? {
|
||||||
return passCodeText.value
|
passCodeText.value
|
||||||
}
|
}
|
||||||
|
|
||||||
public func setPassCodeText(_ value: String?) {
|
public func setPassCodeText(_ value: String?) {
|
||||||
passCodeText.value = value
|
passCodeText.accept(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func reset() {
|
public func reset() {
|
||||||
passCodeText.value = nil
|
passCodeText.accept(nil)
|
||||||
validationResultHolder.value = nil
|
validationResultHolder.accept(nil)
|
||||||
passCodeControllerStateVariable.value = controllerType == .change ? .oldEnter : .enter
|
passCodeControllerStateVariable.accept(operationType == .change ? .oldEnter : .enter)
|
||||||
attemptsNumber = 0
|
attemptsNumber = 0
|
||||||
passCodeHolder.reset()
|
passCodeHolder.reset()
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +135,7 @@ open class BasePassCodeViewModel: BaseViewModel {
|
||||||
|
|
||||||
/// Posibility to use biometrics for authentication
|
/// Posibility to use biometrics for authentication
|
||||||
open var isBiometricsEnabled: Bool {
|
open var isBiometricsEnabled: Bool {
|
||||||
return false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Notify about activation for biometrics. Remember to save user choice
|
/// Notify about activation for biometrics. Remember to save user choice
|
||||||
|
|
@ -149,12 +148,11 @@ open class BasePassCodeViewModel: BaseViewModel {
|
||||||
|
|
||||||
/// Notify after system alert with biometrics
|
/// Notify after system alert with biometrics
|
||||||
open func biometricsAuthEnds() {}
|
open func biometricsAuthEnds() {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension BasePassCodeViewModel {
|
private extension BasePassCodeViewModel {
|
||||||
var validationResultBinder: Binder<PassCodeValidationResult?> {
|
var validationResultBinder: Binder<PassCodeValidationResult?> {
|
||||||
return Binder(self) { model, validationResult in
|
Binder(self) { model, validationResult in
|
||||||
let isValid = validationResult?.isValid ?? false
|
let isValid = validationResult?.isValid ?? false
|
||||||
let passCode = validationResult?.passCode
|
let passCode = validationResult?.passCode
|
||||||
|
|
||||||
|
|
@ -162,13 +160,13 @@ private extension BasePassCodeViewModel {
|
||||||
if isValid, model.passCodeHolder.enterStep == .repeatEnter, let passCode = passCode {
|
if isValid, model.passCodeHolder.enterStep == .repeatEnter, let passCode = passCode {
|
||||||
model.authSucceed(.passCode(passCode))
|
model.authSucceed(.passCode(passCode))
|
||||||
} else {
|
} else {
|
||||||
model.passCodeControllerStateVariable.value = model.passCodeHolder.enterStep
|
model.passCodeControllerStateVariable.accept(model.passCodeHolder.enterStep)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if isValid, let passCode = passCode {
|
if isValid, let passCode = passCode {
|
||||||
model.authSucceed(.passCode(passCode))
|
model.authSucceed(.passCode(passCode))
|
||||||
} else {
|
} else {
|
||||||
model.passCodeControllerStateVariable.value = model.passCodeHolder.enterStep
|
model.passCodeControllerStateVariable.accept(model.passCodeHolder.enterStep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -182,12 +180,12 @@ extension BasePassCodeViewModel {
|
||||||
validateIfNeeded()
|
validateIfNeeded()
|
||||||
|
|
||||||
if shouldUpdateControllerState {
|
if shouldUpdateControllerState {
|
||||||
passCodeControllerStateVariable.value = passCodeHolder.enterStep
|
passCodeControllerStateVariable.accept(passCodeHolder.enterStep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var shouldUpdateControllerState: Bool {
|
private var shouldUpdateControllerState: Bool {
|
||||||
return !passCodeHolder.shouldValidate ||
|
!passCodeHolder.shouldValidate ||
|
||||||
!(validationResultHolder.value?.isValid ?? true) ||
|
!(validationResultHolder.value?.isValid ?? true) ||
|
||||||
validationResultHolder.value?.error?.isTooManyAttempts ?? false
|
validationResultHolder.value?.error?.isTooManyAttempts ?? false
|
||||||
}
|
}
|
||||||
|
|
@ -197,28 +195,41 @@ extension BasePassCodeViewModel {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var validationResult = passCodeHolder.validate()
|
switch passCodeHolder.type {
|
||||||
|
case .create where passCodeHolder.enterStep == .repeatEnter:
|
||||||
let passCodeValidationForPassCodeChange = passCodeHolder.type == .change && passCodeHolder.enterStep == .newEnter
|
|
||||||
|
|
||||||
if passCodeHolder.type == .enter || passCodeValidationForPassCodeChange {
|
|
||||||
attemptsNumber += 1
|
attemptsNumber += 1
|
||||||
|
|
||||||
if let passCode = validationResult.passCode, !isEnteredPassCodeValid(passCode) {
|
case .change where passCodeHolder.enterStep == .repeatEnter:
|
||||||
validationResult = .invalid(.wrongCode(passCodeConfiguration.maxAttemptsNumber - attemptsNumber))
|
attemptsNumber += 1
|
||||||
|
|
||||||
|
case .enter:
|
||||||
|
attemptsNumber += 1
|
||||||
|
|
||||||
|
default:
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validationResult.isValid && attemptsNumber == Int(passCodeConfiguration.maxAttemptsNumber)) ||
|
var validationResult = passCodeHolder.validate()
|
||||||
attemptsNumber > Int(passCodeConfiguration.maxAttemptsNumber) {
|
|
||||||
validationResult = .invalid(.tooManyAttempts)
|
// if entered (in .enter mode) code is invalid -> .wrongCode
|
||||||
|
if passCodeHolder.type == .enter,
|
||||||
|
let passCode = validationResult.passCode,
|
||||||
|
!isEnteredPassCodeValid(passCode) {
|
||||||
|
|
||||||
|
let remainingAttemptsCount = passCodeConfiguration.maxAttemptsNumber - attemptsNumber
|
||||||
|
validationResult = .invalid(.wrongCode(attemptsRemaining: remainingAttemptsCount))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if entered code (in any mode) is mismatched too many times -> .tooManyAttempts
|
||||||
|
if (!validationResult.isValid && attemptsNumber == passCodeConfiguration.maxAttemptsNumber) ||
|
||||||
|
attemptsNumber > passCodeConfiguration.maxAttemptsNumber {
|
||||||
|
validationResult = .invalid(.tooManyAttempts(type: operationType))
|
||||||
}
|
}
|
||||||
|
|
||||||
if !validationResult.isValid {
|
if !validationResult.isValid {
|
||||||
passCodeHolder.reset()
|
passCodeHolder.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
validationResultHolder.value = validationResult
|
validationResultHolder.accept(validationResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,5 +35,4 @@ public extension BaseTextFieldViewEvents {
|
||||||
|
|
||||||
self.init(textChangedDriver: textChangedDriver)
|
self.init(textChangedDriver: textChangedDriver)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Touch Instinct
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the Software), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
// THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
import TableKit
|
|
||||||
|
|
||||||
extension LabelTableViewCell: ConfigurableCell {
|
|
||||||
|
|
||||||
public func configure(with viewModel: LabelCellViewModel) {
|
|
||||||
configureLabelCell(with: viewModel)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -15,7 +15,6 @@ public extension Error {
|
||||||
|
|
||||||
/// Returns: true if server json response is not valid
|
/// Returns: true if server json response is not valid
|
||||||
var isResponseSerializationError: Bool {
|
var isResponseSerializationError: Bool {
|
||||||
return (self as? AFError)?.isResponseSerializationError ?? false
|
(self as? AFError)?.isResponseSerializationError ?? false
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,8 @@ public extension UIBarButtonItem {
|
||||||
|
|
||||||
/// Creates activity indicator view and bar button item (based on activity indicator)
|
/// Creates activity indicator view and bar button item (based on activity indicator)
|
||||||
static var activityIndicator: (barButton: UIBarButtonItem, activityIndicator: UIActivityIndicatorView) {
|
static var activityIndicator: (barButton: UIBarButtonItem, activityIndicator: UIActivityIndicatorView) {
|
||||||
let indicatorView = UIActivityIndicatorView(activityIndicatorStyle: .white)
|
let indicatorView = UIActivityIndicatorView(style: .white)
|
||||||
let indicatorBar = UIBarButtonItem(customView: indicatorView)
|
let indicatorBar = UIBarButtonItem(customView: indicatorView)
|
||||||
return (indicatorBar, indicatorView)
|
return (indicatorBar, indicatorView)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ public extension UserDefaults {
|
||||||
/// Default place to store session id
|
/// Default place to store session id
|
||||||
var sessionId: String? {
|
var sessionId: String? {
|
||||||
get {
|
get {
|
||||||
return string(forKey: Keys.sessionId)
|
string(forKey: Keys.sessionId)
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
set(newValue, forKey: Keys.sessionId)
|
set(newValue, forKey: Keys.sessionId)
|
||||||
|
|
@ -42,11 +42,10 @@ public extension UserDefaults {
|
||||||
/// Default place to store userLogin
|
/// Default place to store userLogin
|
||||||
var userLogin: String? {
|
var userLogin: String? {
|
||||||
get {
|
get {
|
||||||
return string(forKey: Keys.userLogin)
|
string(forKey: Keys.userLogin)
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
set(newValue, forKey: Keys.userLogin)
|
set(newValue, forKey: Keys.userLogin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>FMWK</string>
|
<string>FMWK</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.0.1</string>
|
<string>0.3.13</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
<key>NSPrincipalClass</key>
|
<key>NSPrincipalClass</key>
|
||||||
|
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (c) 2018 Touch Instinct
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files (the Software), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
// THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
import CoreGraphics.CGBase
|
|
||||||
|
|
||||||
/// Protocol with methods for configuration and layout cell.
|
|
||||||
public protocol PinLayoutCell {
|
|
||||||
|
|
||||||
/// Method is called when cell initialized from nib or from code.
|
|
||||||
func initializeCell()
|
|
||||||
|
|
||||||
/// Method for adding subviews to content view.
|
|
||||||
///
|
|
||||||
/// - Returns: Nothing.
|
|
||||||
func addViews()
|
|
||||||
|
|
||||||
/// Method for cofiguring appearance of views.
|
|
||||||
///
|
|
||||||
/// - Returns: Nothing.
|
|
||||||
func configureAppearance()
|
|
||||||
|
|
||||||
/// Method for cofiguring layout and layout properties.
|
|
||||||
///
|
|
||||||
/// - Returns: Nothing.
|
|
||||||
func configureLayout()
|
|
||||||
|
|
||||||
/// Method is called during layout calls.
|
|
||||||
///
|
|
||||||
/// - Returns: Nothing.
|
|
||||||
func layout()
|
|
||||||
|
|
||||||
/// Method for calculating best-fitting cell size.
|
|
||||||
///
|
|
||||||
/// - Parameter containerSize: The size for which the view should calculate its best-fitting size.
|
|
||||||
/// - Returns: Best-fitting size.
|
|
||||||
func layout(with containerSize: CGSize) -> CGSize
|
|
||||||
|
|
||||||
/// Current content height.
|
|
||||||
var contentHeight: CGFloat { get }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -20,14 +20,32 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import LeadKit
|
||||||
|
|
||||||
public extension PinLayoutCell {
|
public protocol LegacyConfigurableController: InitializableView {
|
||||||
|
|
||||||
func initializeCell() {
|
associatedtype ViewModelT
|
||||||
|
|
||||||
|
var viewModel: ViewModelT! { get } // swiftlint:disable:this implicitly_unwrapped_optional
|
||||||
|
|
||||||
|
func configureBarButtons()
|
||||||
|
|
||||||
|
func initialLoadView()
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension LegacyConfigurableController where Self: UIViewController {
|
||||||
|
|
||||||
|
func initializeView() {
|
||||||
|
assertionFailure("Use \(String(describing: initialLoadView)) for UIViewController instead!")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Method that should be called in viewDidLoad method of UIViewController.
|
||||||
|
func initialLoadView() {
|
||||||
addViews()
|
addViews()
|
||||||
configureAppearance()
|
|
||||||
configureLayout()
|
configureLayout()
|
||||||
|
configureAppearance()
|
||||||
|
configureBarButtons()
|
||||||
|
localize()
|
||||||
|
bindViews()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -30,5 +30,4 @@ public protocol OnlineValidateable {
|
||||||
|
|
||||||
/// May contain an error if validation did failed.
|
/// May contain an error if validation did failed.
|
||||||
var error: Error? { get }
|
var error: Error? { get }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ open class BasePassCodeService {
|
||||||
|
|
||||||
/// Override to set specific keychain service name
|
/// Override to set specific keychain service name
|
||||||
open class var keychainServiceString: String {
|
open class var keychainServiceString: String {
|
||||||
return Bundle.main.bundleIdentifier ?? ""
|
Bundle.main.bundleIdentifier ?? ""
|
||||||
}
|
}
|
||||||
|
|
||||||
public init() {
|
public init() {
|
||||||
|
|
@ -55,22 +55,21 @@ open class BasePassCodeService {
|
||||||
private lazy var keychain = Keychain(service: BasePassCodeService.keychainServiceString).synchronizable(false)
|
private lazy var keychain = Keychain(service: BasePassCodeService.keychainServiceString).synchronizable(false)
|
||||||
|
|
||||||
private var passCodeHash: String? {
|
private var passCodeHash: String? {
|
||||||
return keychain[Keys.passCodeHash]
|
keychain[Keys.passCodeHash]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension BasePassCodeService {
|
public extension BasePassCodeService {
|
||||||
|
|
||||||
/// Indicates is pass code already saved on this device
|
/// Indicates is pass code already saved on this device
|
||||||
var isPassCodeSaved: Bool {
|
var isPassCodeSaved: Bool {
|
||||||
return keychain[Keys.passCodeHash] != nil
|
keychain[Keys.passCodeHash] != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Possibility to authenticate via biometrics. TouchID or FaceID
|
/// Possibility to authenticate via biometrics. TouchID or FaceID
|
||||||
var isBiometricsAuthorizationEnabled: Bool {
|
var isBiometricsAuthorizationEnabled: Bool {
|
||||||
get {
|
get {
|
||||||
return keychain[Keys.isBiometricsEnabled] == Values.biometricsEnabled
|
keychain[Keys.isBiometricsEnabled] == Values.biometricsEnabled
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
keychain[Keys.isBiometricsEnabled] = newValue ? Values.biometricsEnabled : nil
|
keychain[Keys.isBiometricsEnabled] = newValue ? Values.biometricsEnabled : nil
|
||||||
|
|
@ -88,7 +87,7 @@ public extension BasePassCodeService {
|
||||||
|
|
||||||
/// Check if pass code is correct
|
/// Check if pass code is correct
|
||||||
func check(passCode: String) -> Bool {
|
func check(passCode: String) -> Bool {
|
||||||
return passCode.sha256() == passCodeHash
|
passCode.sha256() == passCodeHash
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset pass code settings
|
/// Reset pass code settings
|
||||||
|
|
@ -96,5 +95,4 @@ public extension BasePassCodeService {
|
||||||
save(passCode: nil)
|
save(passCode: nil)
|
||||||
isBiometricsAuthorizationEnabled = false
|
isBiometricsAuthorizationEnabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import RxSwift
|
import RxSwift
|
||||||
import LeadKit
|
|
||||||
|
|
||||||
/// Represents service that store basic user information
|
/// Represents service that store basic user information
|
||||||
open class BaseUserService {
|
open class BaseUserService {
|
||||||
|
|
@ -51,7 +50,7 @@ open class BaseUserService {
|
||||||
|
|
||||||
/// Indicates if user is logged in
|
/// Indicates if user is logged in
|
||||||
open var isLoggedIn: Bool {
|
open var isLoggedIn: Bool {
|
||||||
return UserDefaults.standard.sessionId != nil
|
UserDefaults.standard.sessionId != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset user information
|
/// Reset user information
|
||||||
|
|
@ -59,5 +58,4 @@ open class BaseUserService {
|
||||||
UserDefaults.standard.sessionId = nil
|
UserDefaults.standard.sessionId = nil
|
||||||
UserDefaults.standard.userLogin = nil
|
UserDefaults.standard.userLogin = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,54 @@ public typealias BiometricsAuthHandler = (Bool, Error?) -> Void
|
||||||
/// Service that provide access to authentication via biometric
|
/// Service that provide access to authentication via biometric
|
||||||
public final class BiometricsService {
|
public final class BiometricsService {
|
||||||
|
|
||||||
|
public enum BiometryType {
|
||||||
|
|
||||||
|
case faceID
|
||||||
|
|
||||||
|
case touchID
|
||||||
|
|
||||||
|
case none
|
||||||
|
}
|
||||||
|
|
||||||
private lazy var laContext = LAContext()
|
private lazy var laContext = LAContext()
|
||||||
|
|
||||||
|
/// If the user unlocks the device using biometrics within the specified time interval,
|
||||||
|
/// then authentication for the receiver succeeds automatically, without prompting the user for biometrics.
|
||||||
|
/// Works only after device unlock event, no other apps authentications counts.
|
||||||
|
public var allowableReuseDuration: TimeInterval? {
|
||||||
|
didSet {
|
||||||
|
guard let duration = allowableReuseDuration else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if #available(iOS 9.0, *) {
|
||||||
|
laContext.touchIDAuthenticationAllowableReuseDuration = duration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns BiometryType supporting by device: TouchID, FaceID or none
|
||||||
|
public var biometryType: BiometryType {
|
||||||
|
let canEvaluate = canAuthenticateWithBiometrics
|
||||||
|
|
||||||
|
if #available(iOS 11.0, *) {
|
||||||
|
switch laContext.biometryType {
|
||||||
|
case .touchID:
|
||||||
|
return .touchID
|
||||||
|
|
||||||
|
case .faceID:
|
||||||
|
return .faceID
|
||||||
|
|
||||||
|
case .none:
|
||||||
|
return .none
|
||||||
|
|
||||||
|
@unknown default:
|
||||||
|
return .none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return canEvaluate ? .touchID : .none
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns current domain state
|
/// Returns current domain state
|
||||||
public var evaluatedPolicyDomainState: Data? {
|
public var evaluatedPolicyDomainState: Data? {
|
||||||
// We need to call canEvaluatePolicy function for evaluatedPolicyDomainState to be updated
|
// We need to call canEvaluatePolicy function for evaluatedPolicyDomainState to be updated
|
||||||
|
|
@ -36,13 +82,16 @@ public final class BiometricsService {
|
||||||
return laContext.evaluatedPolicyDomainState
|
return laContext.evaluatedPolicyDomainState
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicates is it possible to authenticate on this device via touch id
|
/// Indicates is it possible to authenticate on this device via any biometric.
|
||||||
|
/// Returns false if not enrolled or lockedout.
|
||||||
public var canAuthenticateWithBiometrics: Bool {
|
public var canAuthenticateWithBiometrics: Bool {
|
||||||
return laContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
|
laContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initiates system biometrics authentication process
|
Initiates system biometrics authentication process.
|
||||||
|
Once evaluated, will return success until the context is deallocated.
|
||||||
|
Call "clear" to use a new context instance.
|
||||||
|
|
||||||
- parameters:
|
- parameters:
|
||||||
- description: prompt on the system alert
|
- description: prompt on the system alert
|
||||||
|
|
@ -64,4 +113,10 @@ public final class BiometricsService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Replace old instance of the context with the new one
|
||||||
|
public func clear() {
|
||||||
|
laContext = LAContext()
|
||||||
|
}
|
||||||
|
|
||||||
|
public init() {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,5 +32,4 @@ public enum OnlineValidationState {
|
||||||
case processing
|
case processing
|
||||||
case valid
|
case valid
|
||||||
case invalid(error: Error?)
|
case invalid(error: Error?)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,5 +11,4 @@ public struct ValidationError: Error {
|
||||||
self.errorMessage = errorMessage
|
self.errorMessage = errorMessage
|
||||||
self.errorHint = errorHint
|
self.errorHint = errorHint
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ public extension ValidationItemState {
|
||||||
switch self {
|
switch self {
|
||||||
case .initial:
|
case .initial:
|
||||||
return true
|
return true
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -24,26 +25,26 @@ public extension ValidationItemState {
|
||||||
switch self {
|
switch self {
|
||||||
case .valid:
|
case .valid:
|
||||||
return true
|
return true
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class ValidationItem {
|
public final class ValidationItem {
|
||||||
|
|
||||||
private let disposeBag = DisposeBag()
|
private let disposeBag = DisposeBag()
|
||||||
|
|
||||||
private let validationStateHolder = Variable<ValidationItemState>(.initial)
|
private let validationStateHolder = BehaviorRelay<ValidationItemState>(value: .initial)
|
||||||
public var validationState: ValidationItemState {
|
public var validationState: ValidationItemState {
|
||||||
return validationStateHolder.value
|
validationStateHolder.value
|
||||||
}
|
}
|
||||||
public var validationStateObservable: Observable<ValidationItemState> {
|
public var validationStateObservable: Observable<ValidationItemState> {
|
||||||
return validationStateHolder.asObservable()
|
validationStateHolder.asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
private let text = Variable<String?>(nil)
|
private let text = BehaviorRelay<String?>(value: nil)
|
||||||
|
|
||||||
private(set) var rules: [Rule] = []
|
private(set) var rules: [Rule] = []
|
||||||
|
|
||||||
|
|
@ -58,7 +59,8 @@ public final class ValidationItem {
|
||||||
.drive(text)
|
.drive(text)
|
||||||
.disposed(by: disposeBag)
|
.disposed(by: disposeBag)
|
||||||
|
|
||||||
textDriver.asObservable().withLatestFrom(validationStateHolder.asObservable()) { (text: $0, validationState: $1) }
|
textDriver.asObservable()
|
||||||
|
.withLatestFrom(validationStateHolder.asObservable()) { (text: $0, validationState: $1) }
|
||||||
.filter { !$0.validationState.isInitial }
|
.filter { !$0.validationState.isInitial }
|
||||||
.map { $0.text }
|
.map { $0.text }
|
||||||
.subscribe(onNext: { [weak self] text in
|
.subscribe(onNext: { [weak self] text in
|
||||||
|
|
@ -88,13 +90,13 @@ public final class ValidationItem {
|
||||||
.correction where !isManual,
|
.correction where !isManual,
|
||||||
.valid where !isManual:
|
.valid where !isManual:
|
||||||
|
|
||||||
validationStateHolder.value = .correction(validationError)
|
validationStateHolder.accept(.correction(validationError))
|
||||||
|
|
||||||
default:
|
default:
|
||||||
validationStateHolder.value = .error(validationError)
|
validationStateHolder.accept(.error(validationError))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
validationStateHolder.value = .valid
|
validationStateHolder.accept(.valid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,8 @@ public enum ValidationServiceState {
|
||||||
public extension ValidationServiceState {
|
public extension ValidationServiceState {
|
||||||
|
|
||||||
var isValid: Bool {
|
var isValid: Bool {
|
||||||
return self == .valid
|
self == .valid
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class ValidationService {
|
public final class ValidationService {
|
||||||
|
|
@ -28,12 +27,12 @@ public final class ValidationService {
|
||||||
|
|
||||||
private(set) var validationItems: [ValidationItem] = []
|
private(set) var validationItems: [ValidationItem] = []
|
||||||
|
|
||||||
private let stateHolder = Variable<ValidationServiceState>(.initial)
|
private let stateHolder = BehaviorRelay<ValidationServiceState>(value: .initial)
|
||||||
public var state: ValidationServiceState {
|
public var state: ValidationServiceState {
|
||||||
return stateHolder.value
|
stateHolder.value
|
||||||
}
|
}
|
||||||
public var stateObservable: Observable<ValidationServiceState> {
|
public var stateObservable: Observable<ValidationServiceState> {
|
||||||
return stateHolder.asObservable()
|
stateHolder.asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var validationStateReactType: ValidationServiceStateReactType = .none
|
private var validationStateReactType: ValidationServiceStateReactType = .none
|
||||||
|
|
@ -62,7 +61,7 @@ public final class ValidationService {
|
||||||
|
|
||||||
public func unregister(items: [ValidationItem]) {
|
public func unregister(items: [ValidationItem]) {
|
||||||
items.forEach { item in
|
items.forEach { item in
|
||||||
if let removeIndex = validationItems.index(where: { $0 === item }) {
|
if let removeIndex = validationItems.firstIndex(where: { $0 === item }) {
|
||||||
validationItems.remove(at: removeIndex)
|
validationItems.remove(at: removeIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +71,7 @@ public final class ValidationService {
|
||||||
|
|
||||||
public func validate() -> Bool {
|
public func validate() -> Bool {
|
||||||
validationStateReactType = .all
|
validationStateReactType = .all
|
||||||
let isValid = validationItems.map { $0.manualValidate() }.reduce(true) { $0 && $1 }
|
let isValid = validationItems.allSatisfy { $0.manualValidate() }
|
||||||
validationStateReactType = .each
|
validationStateReactType = .each
|
||||||
|
|
||||||
return isValid
|
return isValid
|
||||||
|
|
@ -85,23 +84,26 @@ public final class ValidationService {
|
||||||
|
|
||||||
let zipStates = Observable
|
let zipStates = Observable
|
||||||
.zip(allValidationStateObservables) { $0 }
|
.zip(allValidationStateObservables) { $0 }
|
||||||
.filter { [weak self] _ in self?.validationStateReactType == .all }
|
.filter { [weak self] _ in
|
||||||
|
self?.validationStateReactType == .all
|
||||||
|
}
|
||||||
|
|
||||||
let combineLatestStates = Observable
|
let combineLatestStates = Observable
|
||||||
.combineLatest(allValidationStateObservables) { $0 }
|
.combineLatest(allValidationStateObservables) { $0 }
|
||||||
.filter { [weak self] _ in self?.validationStateReactType == .each }
|
.filter { [weak self] _ in
|
||||||
|
self?.validationStateReactType == .each
|
||||||
|
}
|
||||||
|
|
||||||
let stateObservables = [zipStates, combineLatestStates]
|
let stateObservables = [zipStates, combineLatestStates]
|
||||||
|
|
||||||
stateObservables.forEach { observable in
|
stateObservables.forEach { observable in
|
||||||
observable
|
observable
|
||||||
.map { states -> Bool in
|
.map { states -> Bool in
|
||||||
states.map { $0.isValid }.reduce(true) { $0 && $1 }
|
states.allSatisfy { $0.isValid }
|
||||||
}
|
}
|
||||||
.map { $0 ? ValidationServiceState.valid : .invalid }
|
.map { $0 ? ValidationServiceState.valid : .invalid }
|
||||||
.bind(to: stateHolder)
|
.bind(to: stateHolder)
|
||||||
.disposed(by: disposeBag)
|
.disposed(by: disposeBag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 622b2d34508fe0d4103af643bc0d91c75f7bf026
|
Subproject commit 2799169e2103c034b0e1be221860a23292766f36
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
readonly CONFIG_PATH=${PROJECT_DIR}/build-scripts/xcode/.swiftlint.yml
|
||||||
|
|
||||||
|
readonly SWIFTLINT_VERSION=0.45.1
|
||||||
|
readonly SWIFTLINT_PORTABLE_FILENAME=portable_swiftlint.zip
|
||||||
|
|
||||||
|
readonly SWIFTLINT_PORTABLE_URL=https://github.com/realm/SwiftLint/releases/download/${SWIFTLINT_VERSION}/${SWIFTLINT_PORTABLE_FILENAME}
|
||||||
|
|
||||||
|
. build-scripts/xcode/aux_scripts/download_file.sh ${SWIFTLINT_PORTABLE_FILENAME} ${SWIFTLINT_PORTABLE_URL} Downloads --remove-cached
|
||||||
|
|
||||||
|
cd Downloads && unzip -o ${SWIFTLINT_PORTABLE_FILENAME}
|
||||||
|
|
||||||
|
${PROJECT_DIR}/Downloads/swiftlint autocorrect --path ${PROJECT_DIR}/Sources --config ${CONFIG_PATH} && ${PROJECT_DIR}/Downloads/swiftlint --path ${PROJECT_DIR}/Sources --config ${CONFIG_PATH}
|
||||||
Loading…
Reference in New Issue