Merge branch 'master' into feature/usefull
This commit is contained in:
commit
bf69f5e782
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = "LeadKit"
|
||||
s.version = "0.5.0"
|
||||
s.version = "0.5.1"
|
||||
s.summary = "iOS framework with a bunch of tools for rapid development"
|
||||
s.homepage = "https://github.com/TouchInstinct/LeadKit"
|
||||
s.license = "Apache License, Version 2.0"
|
||||
|
|
@ -42,10 +42,11 @@ Pod::Spec.new do |s|
|
|||
ss.watchos.exclude_files = [
|
||||
"LeadKit/Sources/Classes/Pagination/PaginationTableViewWrapper.swift",
|
||||
"LeadKit/Sources/Classes/Views/XibView.swift",
|
||||
"LeadKit/Sources/Classes/Views/SpinnerView.swift",
|
||||
"LeadKit/Sources/Extensions/CABasicAnimation/*",
|
||||
"LeadKit/Sources/Extensions/CGFloat/CGFloat+Pixels.swift",
|
||||
"LeadKit/Sources/Extensions/NetworkService/NetworkService+ActivityIndicator.swift",
|
||||
"LeadKit/Sources/Extensions/NetworkService/NetworkService+RxLoadImage.swift",
|
||||
"LeadKit/Sources/Extensions/Observable/Observable+ToastErrorLogging.swift",
|
||||
"LeadKit/Sources/Extensions/PaginationTableViewWrapperDelegate/PaginationTableViewWrapperDelegate+DefaultImplementation.swift",
|
||||
"LeadKit/Sources/Extensions/StoryboardProtocol/*",
|
||||
"LeadKit/Sources/Extensions/Support/UIScrollView+Support.swift",
|
||||
|
|
@ -69,7 +70,6 @@ Pod::Spec.new do |s|
|
|||
"LeadKit/Sources/Classes/Pagination/PaginationTableViewWrapper.swift",
|
||||
"LeadKit/Sources/Structures/Drawing/CALayerDrawingOperation.swift",
|
||||
"LeadKit/Sources/Extensions/NetworkService/NetworkService+ActivityIndicator.swift",
|
||||
"LeadKit/Sources/Extensions/Observable/Observable+ToastErrorLogging.swift",
|
||||
"LeadKit/Sources/Extensions/PaginationTableViewWrapperDelegate/PaginationTableViewWrapperDelegate+DefaultImplementation.swift",
|
||||
"LeadKit/Sources/Extensions/Support/UIScrollView+Support.swift",
|
||||
"LeadKit/Sources/Extensions/TableDirector/TableDirector+Extensions.swift",
|
||||
|
|
@ -81,7 +81,6 @@ Pod::Spec.new do |s|
|
|||
ss.dependency "RxAlamofire", '3.0.2'
|
||||
ss.dependency "ObjectMapper", '~> 2.2'
|
||||
|
||||
ss.ios.dependency "Toast-Swift", '~> 2.0.0'
|
||||
ss.ios.dependency "TableKit", '~> 2.3.1'
|
||||
ss.ios.dependency "UIScrollView-InfiniteScroll", '~> 1.0.0'
|
||||
end
|
||||
|
|
@ -94,13 +93,10 @@ Pod::Spec.new do |s|
|
|||
ss.exclude_files = [
|
||||
"LeadKit/Sources/Classes/Pagination/PaginationTableViewWrapper.swift",
|
||||
"LeadKit/Sources/Extensions/NetworkService/NetworkService+ActivityIndicator.swift",
|
||||
"LeadKit/Sources/Extensions/Observable/Observable+ToastErrorLogging.swift",
|
||||
"LeadKit/Sources/Extensions/PaginationTableViewWrapperDelegate/PaginationTableViewWrapperDelegate+DefaultImplementation.swift",
|
||||
"LeadKit/Sources/Extensions/TableDirector/TableDirector+Extensions.swift",
|
||||
]
|
||||
|
||||
ss.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => 'LEADKIT_EXTENSION_TARGET' }
|
||||
|
||||
ss.dependency "CocoaLumberjack/Swift", '~> 3.1.0'
|
||||
ss.dependency "RxSwift", '3.4.0'
|
||||
ss.dependency "RxCocoa", '3.4.0'
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@
|
|||
2D6A0E6105F4A9BF22BF4BB1 /* Pods_LeadKit_iOS_ExtensionsTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C88ED8C9373F85C06697849 /* Pods_LeadKit_iOS_ExtensionsTests.framework */; };
|
||||
2D96F18874B9519F5AD74003 /* Pods_LeadKit_LeadKit_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0F8D0002B21A4F31981F1ED /* Pods_LeadKit_LeadKit_tvOS.framework */; };
|
||||
3614FEACB9E8313C87F7C393 /* Pods_LeadKit_tvOSTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4DB1CCAB1EAAACD3AC42C795 /* Pods_LeadKit_tvOSTests.framework */; };
|
||||
67051ADB1EBC7C36008EADC0 /* SpinnerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67051ADA1EBC7C36008EADC0 /* SpinnerView.swift */; };
|
||||
67051ADC1EBC7C36008EADC0 /* SpinnerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67051ADA1EBC7C36008EADC0 /* SpinnerView.swift */; };
|
||||
67051ADD1EBC7C36008EADC0 /* SpinnerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67051ADA1EBC7C36008EADC0 /* SpinnerView.swift */; };
|
||||
671462441EB3396E00EAB194 /* Mutex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671461C61EB3396E00EAB194 /* Mutex.swift */; };
|
||||
671462451EB3396E00EAB194 /* Mutex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671461C61EB3396E00EAB194 /* Mutex.swift */; };
|
||||
671462461EB3396E00EAB194 /* Mutex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671461C61EB3396E00EAB194 /* Mutex.swift */; };
|
||||
|
|
@ -113,7 +116,6 @@
|
|||
671462AD1EB3396E00EAB194 /* Observable+DeferredJust.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671461F11EB3396E00EAB194 /* Observable+DeferredJust.swift */; };
|
||||
671462AE1EB3396E00EAB194 /* Observable+DeferredJust.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671461F11EB3396E00EAB194 /* Observable+DeferredJust.swift */; };
|
||||
671462AF1EB3396E00EAB194 /* Observable+DeferredJust.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671461F11EB3396E00EAB194 /* Observable+DeferredJust.swift */; };
|
||||
671462B01EB3396E00EAB194 /* Observable+ToastErrorLogging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671461F21EB3396E00EAB194 /* Observable+ToastErrorLogging.swift */; };
|
||||
671462B41EB3396E00EAB194 /* PaginationTableViewWrapperDelegate+DefaultImplementation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671461F41EB3396E00EAB194 /* PaginationTableViewWrapperDelegate+DefaultImplementation.swift */; };
|
||||
671462B81EB3396E00EAB194 /* Sequence+ConcurrentMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671461F61EB3396E00EAB194 /* Sequence+ConcurrentMap.swift */; };
|
||||
671462B91EB3396E00EAB194 /* Sequence+ConcurrentMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671461F61EB3396E00EAB194 /* Sequence+ConcurrentMap.swift */; };
|
||||
|
|
@ -351,10 +353,20 @@
|
|||
67952C3D1EB3266200B3BA1A /* LeadKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 67186B201EB247A200CFAFFB /* LeadKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
67952DCE1EB327B500B3BA1A /* LeadKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 67952DC51EB327B400B3BA1A /* LeadKit.framework */; };
|
||||
67952DDD1EB3281300B3BA1A /* LeadKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 67186B201EB247A200CFAFFB /* LeadKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
67A1FF8F1EBCA09B00D6C89F /* UIImage+Spinner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A1FF8E1EBCA09B00D6C89F /* UIImage+Spinner.swift */; };
|
||||
67A1FF901EBCA09B00D6C89F /* UIImage+Spinner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A1FF8E1EBCA09B00D6C89F /* UIImage+Spinner.swift */; };
|
||||
67A1FF911EBCA09B00D6C89F /* UIImage+Spinner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A1FF8E1EBCA09B00D6C89F /* UIImage+Spinner.swift */; };
|
||||
67A1FF941EBCA65E00D6C89F /* CABasicAnimation+Rotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A1FF931EBCA65E00D6C89F /* CABasicAnimation+Rotation.swift */; };
|
||||
67A1FF951EBCA65E00D6C89F /* CABasicAnimation+Rotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A1FF931EBCA65E00D6C89F /* CABasicAnimation+Rotation.swift */; };
|
||||
67A1FF971EBCA65E00D6C89F /* CABasicAnimation+Rotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A1FF931EBCA65E00D6C89F /* CABasicAnimation+Rotation.swift */; };
|
||||
67CDEE401EB369BF00895905 /* ConfigurableController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671462241EB3396E00EAB194 /* ConfigurableController.swift */; };
|
||||
67CDEE421EB3AD1C00895905 /* NetworkService+RxLoadImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67CDEE411EB3AD1C00895905 /* NetworkService+RxLoadImage.swift */; };
|
||||
67CDEE431EB3AD1C00895905 /* NetworkService+RxLoadImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67CDEE411EB3AD1C00895905 /* NetworkService+RxLoadImage.swift */; };
|
||||
67CDEE441EB3AD1C00895905 /* NetworkService+RxLoadImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67CDEE411EB3AD1C00895905 /* NetworkService+RxLoadImage.swift */; };
|
||||
67E6C2351EBB32F5007842A6 /* SingleLoadCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E6C2341EBB32F5007842A6 /* SingleLoadCursor.swift */; };
|
||||
67E6C2361EBB32F5007842A6 /* SingleLoadCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E6C2341EBB32F5007842A6 /* SingleLoadCursor.swift */; };
|
||||
67E6C2371EBB32F5007842A6 /* SingleLoadCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E6C2341EBB32F5007842A6 /* SingleLoadCursor.swift */; };
|
||||
67E6C2381EBB32F5007842A6 /* SingleLoadCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E6C2341EBB32F5007842A6 /* SingleLoadCursor.swift */; };
|
||||
BA6C6DB45950382041948FC5 /* Pods_LeadKit_LeadKit_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CFE9323150A9760008093F73 /* Pods_LeadKit_LeadKit_iOS.framework */; };
|
||||
D6EE55093E404DEA62B03DDF /* Pods_LeadKit_LeadKit_watchOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8590CA7831555C295C5DC572 /* Pods_LeadKit_LeadKit_watchOS.framework */; };
|
||||
DEE25FE98D40ED1C168F384A /* Pods_LeadKit_LeadKit_iOS_Extensions.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 887F99C5326BD220C2811BD6 /* Pods_LeadKit_LeadKit_iOS_Extensions.framework */; };
|
||||
|
|
@ -416,6 +428,7 @@
|
|||
563DDE9CACD515FDCB5A2FFF /* Pods-LeadKit-LeadKit tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeadKit-LeadKit tvOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-LeadKit-LeadKit tvOS/Pods-LeadKit-LeadKit tvOS.release.xcconfig"; sourceTree = "<group>"; };
|
||||
56C11305E2B44404FFFD12AA /* Pods_LeadKit_watchOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_watchOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
65B19DB0B65A1EE1A1E2C907 /* Pods-LeadKit tvOSTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeadKit tvOSTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-LeadKit tvOSTests/Pods-LeadKit tvOSTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
67051ADA1EBC7C36008EADC0 /* SpinnerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpinnerView.swift; sourceTree = "<group>"; };
|
||||
671461C61EB3396E00EAB194 /* Mutex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Mutex.swift; sourceTree = "<group>"; };
|
||||
671461C81EB3396E00EAB194 /* FixedPageCursor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FixedPageCursor.swift; sourceTree = "<group>"; };
|
||||
671461C91EB3396E00EAB194 /* MapCursor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapCursor.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -443,7 +456,6 @@
|
|||
671461ED1EB3396E00EAB194 /* IndexPath+ImmutableIndexPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "IndexPath+ImmutableIndexPath.swift"; sourceTree = "<group>"; };
|
||||
671461EF1EB3396E00EAB194 /* ImmutableMappable+ObservableMappable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ImmutableMappable+ObservableMappable.swift"; sourceTree = "<group>"; };
|
||||
671461F11EB3396E00EAB194 /* Observable+DeferredJust.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+DeferredJust.swift"; sourceTree = "<group>"; };
|
||||
671461F21EB3396E00EAB194 /* Observable+ToastErrorLogging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+ToastErrorLogging.swift"; sourceTree = "<group>"; };
|
||||
671461F41EB3396E00EAB194 /* PaginationTableViewWrapperDelegate+DefaultImplementation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "PaginationTableViewWrapperDelegate+DefaultImplementation.swift"; sourceTree = "<group>"; };
|
||||
671461F61EB3396E00EAB194 /* Sequence+ConcurrentMap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Sequence+ConcurrentMap.swift"; sourceTree = "<group>"; };
|
||||
671461F81EB3396E00EAB194 /* StoryboardProtocol+DefaultBundle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "StoryboardProtocol+DefaultBundle.swift"; sourceTree = "<group>"; };
|
||||
|
|
@ -528,7 +540,10 @@
|
|||
67952DCD1EB327B400B3BA1A /* LeadKit iOS ExtensionsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "LeadKit iOS ExtensionsTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
67952DDC1EB3280900B3BA1A /* Info-iOS-Extensions.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-iOS-Extensions.plist"; sourceTree = "<group>"; };
|
||||
67952DDE1EB3285A00B3BA1A /* Info-iOS-Extensions.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-iOS-Extensions.plist"; sourceTree = "<group>"; };
|
||||
67A1FF8E1EBCA09B00D6C89F /* UIImage+Spinner.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Spinner.swift"; sourceTree = "<group>"; };
|
||||
67A1FF931EBCA65E00D6C89F /* CABasicAnimation+Rotation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CABasicAnimation+Rotation.swift"; sourceTree = "<group>"; };
|
||||
67CDEE411EB3AD1C00895905 /* NetworkService+RxLoadImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NetworkService+RxLoadImage.swift"; sourceTree = "<group>"; };
|
||||
67E6C2341EBB32F5007842A6 /* SingleLoadCursor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleLoadCursor.swift; sourceTree = "<group>"; };
|
||||
78405D3B3D3C3E17456877FF /* Pods_LeadKit_iOSTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_iOSTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8590CA7831555C295C5DC572 /* Pods_LeadKit_LeadKit_watchOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_LeadKit_watchOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
887F99C5326BD220C2811BD6 /* Pods_LeadKit_LeadKit_iOS_Extensions.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_LeadKit_iOS_Extensions.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
|
@ -638,6 +653,7 @@
|
|||
671461C81EB3396E00EAB194 /* FixedPageCursor.swift */,
|
||||
671461C91EB3396E00EAB194 /* MapCursor.swift */,
|
||||
671461CA1EB3396E00EAB194 /* StaticCursor.swift */,
|
||||
67E6C2341EBB32F5007842A6 /* SingleLoadCursor.swift */,
|
||||
);
|
||||
path = Cursors;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -673,6 +689,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
671461D51EB3396E00EAB194 /* XibView.swift */,
|
||||
67051ADA1EBC7C36008EADC0 /* SpinnerView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -692,6 +709,7 @@
|
|||
children = (
|
||||
671461DB1EB3396E00EAB194 /* Alamofire */,
|
||||
EFBE57CE1EC35ED90040E00A /* Array */,
|
||||
67A1FF921EBCA64A00D6C89F /* CABasicAnimation */,
|
||||
671461DE1EB3396E00EAB194 /* CGContext */,
|
||||
671461E01EB3396E00EAB194 /* CGFloat */,
|
||||
671461E21EB3396E00EAB194 /* CGImage */,
|
||||
|
|
@ -803,7 +821,6 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
671461F11EB3396E00EAB194 /* Observable+DeferredJust.swift */,
|
||||
671461F21EB3396E00EAB194 /* Observable+ToastErrorLogging.swift */,
|
||||
);
|
||||
path = Observable;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -904,6 +921,7 @@
|
|||
children = (
|
||||
6714620D1EB3396E00EAB194 /* UIImage+Extensions.swift */,
|
||||
6714620E1EB3396E00EAB194 /* UIImage+SupportExtensions.swift */,
|
||||
67A1FF8E1EBCA09B00D6C89F /* UIImage+Spinner.swift */,
|
||||
);
|
||||
path = UIImage;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -1102,6 +1120,14 @@
|
|||
path = Tests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
67A1FF921EBCA64A00D6C89F /* CABasicAnimation */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
67A1FF931EBCA65E00D6C89F /* CABasicAnimation+Rotation.swift */,
|
||||
);
|
||||
path = CABasicAnimation;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
78CFEE201C5C456B00F50370 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -1897,6 +1923,7 @@
|
|||
671462441EB3396E00EAB194 /* Mutex.swift in Sources */,
|
||||
671463401EB3396E00EAB194 /* ModuleConfigurator.swift in Sources */,
|
||||
671462641EB3396E00EAB194 /* PaginationViewModel.swift in Sources */,
|
||||
67A1FF8F1EBCA09B00D6C89F /* UIImage+Spinner.swift in Sources */,
|
||||
671462901EB3396E00EAB194 /* CGImage+Crop.swift in Sources */,
|
||||
671462FC1EB3396E00EAB194 /* UIView+DefaultXibName.swift in Sources */,
|
||||
671463841EB3396E00EAB194 /* ResizeDrawingOperation.swift in Sources */,
|
||||
|
|
@ -1905,7 +1932,9 @@
|
|||
6714630C1EB3396E00EAB194 /* UIViewController+DefaultStoryboardIdentifier.swift in Sources */,
|
||||
671462981EB3396E00EAB194 /* CGSize+Resize.swift in Sources */,
|
||||
671462F81EB3396E00EAB194 /* UIView+DefaultReuseIdentifier.swift in Sources */,
|
||||
67051ADB1EBC7C36008EADC0 /* SpinnerView.swift in Sources */,
|
||||
671463581EB3396E00EAB194 /* StoryboardIdentifierProtocol.swift in Sources */,
|
||||
67A1FF941EBCA65E00D6C89F /* CABasicAnimation+Rotation.swift in Sources */,
|
||||
671463301EB3396E00EAB194 /* CursorType.swift in Sources */,
|
||||
6714624C1EB3396E00EAB194 /* MapCursor.swift in Sources */,
|
||||
671463241EB3396E00EAB194 /* Any+TypeName.swift in Sources */,
|
||||
|
|
@ -1945,13 +1974,13 @@
|
|||
671463141EB3396E00EAB194 /* UIViewController+TopVisibleViewController.swift in Sources */,
|
||||
671462881EB3396E00EAB194 /* CGFloat+Pixels.swift in Sources */,
|
||||
671462941EB3396E00EAB194 /* CGSize+CGContextSize.swift in Sources */,
|
||||
671462B01EB3396E00EAB194 /* Observable+ToastErrorLogging.swift in Sources */,
|
||||
671463641EB3396E00EAB194 /* ViewHeightProtocol.swift in Sources */,
|
||||
671462481EB3396E00EAB194 /* FixedPageCursor.swift in Sources */,
|
||||
671462C81EB3396E00EAB194 /* String+Localization.swift in Sources */,
|
||||
671462B81EB3396E00EAB194 /* Sequence+ConcurrentMap.swift in Sources */,
|
||||
671463741EB3396E00EAB194 /* BorderDrawingOperation.swift in Sources */,
|
||||
6714633C1EB3396E00EAB194 /* LoadingIndicator.swift in Sources */,
|
||||
67E6C2351EBB32F5007842A6 /* SingleLoadCursor.swift in Sources */,
|
||||
671463181EB3396E00EAB194 /* UIWindow+Extensions.swift in Sources */,
|
||||
671462541EB3396E00EAB194 /* App.swift in Sources */,
|
||||
6714635C1EB3396E00EAB194 /* StoryboardProtocol.swift in Sources */,
|
||||
|
|
@ -1996,6 +2025,7 @@
|
|||
EFBE57D21EC35EF20040E00A /* Array+Extensions.swift in Sources */,
|
||||
671462821EB3396E00EAB194 /* AlamofireRequest+Extensions.swift in Sources */,
|
||||
671462C61EB3396E00EAB194 /* String+Extensions.swift in Sources */,
|
||||
67E6C2371EBB32F5007842A6 /* SingleLoadCursor.swift in Sources */,
|
||||
671463561EB3396E00EAB194 /* StaticViewHeightProtocol.swift in Sources */,
|
||||
671462AA1EB3396E00EAB194 /* ImmutableMappable+ObservableMappable.swift in Sources */,
|
||||
671463621EB3396E00EAB194 /* SupportProtocol.swift in Sources */,
|
||||
|
|
@ -2111,6 +2141,7 @@
|
|||
671462A71EB3396E00EAB194 /* IndexPath+ImmutableIndexPath.swift in Sources */,
|
||||
671462BF1EB3396E00EAB194 /* StoryboardProtocol+DefaultBundle.swift in Sources */,
|
||||
EFBE57DE1EC361620040E00A /* UIView+Layout.swift in Sources */,
|
||||
67A1FF971EBCA65E00D6C89F /* CABasicAnimation+Rotation.swift in Sources */,
|
||||
671462A31EB3396E00EAB194 /* Double+Rounding.swift in Sources */,
|
||||
6714625F1EB3396E00EAB194 /* LogFormatter.swift in Sources */,
|
||||
6714630B1EB3396E00EAB194 /* UIView+Rotation.swift in Sources */,
|
||||
|
|
@ -2126,6 +2157,7 @@
|
|||
6714628B1EB3396E00EAB194 /* CGFloat+Pixels.swift in Sources */,
|
||||
671462971EB3396E00EAB194 /* CGSize+CGContextSize.swift in Sources */,
|
||||
671463671EB3396E00EAB194 /* ViewHeightProtocol.swift in Sources */,
|
||||
67A1FF911EBCA09B00D6C89F /* UIImage+Spinner.swift in Sources */,
|
||||
6714624B1EB3396E00EAB194 /* FixedPageCursor.swift in Sources */,
|
||||
671462CB1EB3396E00EAB194 /* String+Localization.swift in Sources */,
|
||||
671462BB1EB3396E00EAB194 /* Sequence+ConcurrentMap.swift in Sources */,
|
||||
|
|
@ -2139,9 +2171,11 @@
|
|||
6714633B1EB3396E00EAB194 /* EstimatedViewHeightProtocol.swift in Sources */,
|
||||
6714632F1EB3396E00EAB194 /* ConfigurableController.swift in Sources */,
|
||||
6714628F1EB3396E00EAB194 /* CGImage+Alpha.swift in Sources */,
|
||||
67051ADD1EBC7C36008EADC0 /* SpinnerView.swift in Sources */,
|
||||
671462771EB3396E00EAB194 /* LeadKitError.swift in Sources */,
|
||||
671462DB1EB3396E00EAB194 /* TimeInterval+DateComponents.swift in Sources */,
|
||||
6714638F1EB3396E00EAB194 /* SolidFillDrawingOperation.swift in Sources */,
|
||||
67E6C2381EBB32F5007842A6 /* SingleLoadCursor.swift in Sources */,
|
||||
671462531EB3396E00EAB194 /* StaticCursor.swift in Sources */,
|
||||
6714629F1EB3396E00EAB194 /* CursorType+Slice.swift in Sources */,
|
||||
6714636B1EB3396E00EAB194 /* ViewModelProtocol.swift in Sources */,
|
||||
|
|
@ -2170,8 +2204,10 @@
|
|||
671463491EB3396E00EAB194 /* ResettableType.swift in Sources */,
|
||||
671462E51EB3396E00EAB194 /* UIColor+Hex.swift in Sources */,
|
||||
671462CD1EB3396E00EAB194 /* String+SizeCalculation.swift in Sources */,
|
||||
67A1FF951EBCA65E00D6C89F /* CABasicAnimation+Rotation.swift in Sources */,
|
||||
671462811EB3396E00EAB194 /* AlamofireRequest+Extensions.swift in Sources */,
|
||||
671462C51EB3396E00EAB194 /* String+Extensions.swift in Sources */,
|
||||
67E6C2361EBB32F5007842A6 /* SingleLoadCursor.swift in Sources */,
|
||||
671463551EB3396E00EAB194 /* StaticViewHeightProtocol.swift in Sources */,
|
||||
671462A91EB3396E00EAB194 /* ImmutableMappable+ObservableMappable.swift in Sources */,
|
||||
671463611EB3396E00EAB194 /* SupportProtocol.swift in Sources */,
|
||||
|
|
@ -2186,6 +2222,7 @@
|
|||
671463411EB3396E00EAB194 /* ModuleConfigurator.swift in Sources */,
|
||||
671462651EB3396E00EAB194 /* PaginationViewModel.swift in Sources */,
|
||||
671462911EB3396E00EAB194 /* CGImage+Crop.swift in Sources */,
|
||||
67051ADC1EBC7C36008EADC0 /* SpinnerView.swift in Sources */,
|
||||
671462FD1EB3396E00EAB194 /* UIView+DefaultXibName.swift in Sources */,
|
||||
671463851EB3396E00EAB194 /* ResizeDrawingOperation.swift in Sources */,
|
||||
671462D11EB3396E00EAB194 /* UIScrollView+Support.swift in Sources */,
|
||||
|
|
@ -2239,6 +2276,7 @@
|
|||
EFBE57DC1EC361620040E00A /* UIView+Layout.swift in Sources */,
|
||||
671462551EB3396E00EAB194 /* App.swift in Sources */,
|
||||
6714635D1EB3396E00EAB194 /* StoryboardProtocol.swift in Sources */,
|
||||
67A1FF901EBCA09B00D6C89F /* UIImage+Spinner.swift in Sources */,
|
||||
671462F51EB3396E00EAB194 /* UIStoryboard+InstantiateViewController.swift in Sources */,
|
||||
671463791EB3396E00EAB194 /* CALayerDrawingOperation.swift in Sources */,
|
||||
671463391EB3396E00EAB194 /* EstimatedViewHeightProtocol.swift in Sources */,
|
||||
|
|
@ -2549,7 +2587,7 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = "ru.touchin.LeadKit-iOS-Extensions";
|
||||
PRODUCT_NAME = LeadKit;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG LEADKIT_EXTENSION_TARGET";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_VERSION = 3.0;
|
||||
};
|
||||
name = Debug;
|
||||
|
|
@ -2575,7 +2613,6 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = "ru.touchin.LeadKit-iOS-Extensions";
|
||||
PRODUCT_NAME = LeadKit;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = LEADKIT_EXTENSION_TARGET;
|
||||
SWIFT_VERSION = 3.0;
|
||||
};
|
||||
name = Release;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ abstract_target 'LeadKit' do
|
|||
|
||||
use_frameworks!
|
||||
|
||||
pod "Toast-Swift", '~> 2.0.0'
|
||||
pod "TableKit", '~> 2.3.1'
|
||||
pod "UIScrollView-InfiniteScroll", '~> 1.0.0'
|
||||
|
||||
|
|
|
|||
|
|
@ -49,10 +49,10 @@ public class FixedPageCursor<Cursor: CursorType>: CursorType {
|
|||
return cursor[index]
|
||||
}
|
||||
|
||||
public func loadNextBatch() -> Observable<[Cursor.Element]> {
|
||||
return Observable.deferred {
|
||||
public func loadNextBatch() -> Single<[Cursor.Element]> {
|
||||
return Single.deferred {
|
||||
if self.exhausted {
|
||||
throw CursorError.exhausted
|
||||
return .error(CursorError.exhausted)
|
||||
}
|
||||
|
||||
let restOfLoaded = self.cursor.count - self.count
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ public class MapCursor<Cursor: CursorType, T>: CursorType {
|
|||
return elements[index]
|
||||
}
|
||||
|
||||
public func loadNextBatch() -> Observable<[T]> {
|
||||
public func loadNextBatch() -> Single<[T]> {
|
||||
return cursor.loadNextBatch().map { newItems in
|
||||
let transformedNewItems = newItems.flatMap(self.transform)
|
||||
self.elements += transformedNewItems
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
//
|
||||
// Copyright (c) 2017 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 RxSwift
|
||||
|
||||
/// Cursor implementation for single load operation
|
||||
public class SingleLoadCursor<Element>: ResettableCursorType {
|
||||
|
||||
private let loadingObservable: Single<[Element]>
|
||||
|
||||
private var content: [Element] = []
|
||||
|
||||
/// Initializer for array content type
|
||||
///
|
||||
/// - Parameter loadingObservable: Single observable with element of [Element] type
|
||||
public init(loadingObservable: Single<[Element]>) {
|
||||
self.loadingObservable = loadingObservable
|
||||
}
|
||||
|
||||
public required init(initialFrom other: SingleLoadCursor) {
|
||||
self.loadingObservable = other.loadingObservable
|
||||
}
|
||||
|
||||
public private(set) var exhausted = false
|
||||
|
||||
public var count: Int {
|
||||
return content.count
|
||||
}
|
||||
|
||||
public subscript(index: Int) -> Element {
|
||||
return content[index]
|
||||
}
|
||||
|
||||
public func loadNextBatch() -> Single<[Element]> {
|
||||
return Single.deferred {
|
||||
if self.exhausted {
|
||||
return .error(CursorError.exhausted)
|
||||
}
|
||||
|
||||
return self.loadingObservable.do(onNext: { [weak self] newItems in
|
||||
self?.onGot(result: newItems)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private func onGot(result: [Element]) {
|
||||
content = result
|
||||
exhausted = true
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -29,7 +29,7 @@ public class StaticCursor<Element>: ResettableCursorType {
|
|||
|
||||
/// Initializer for array content type
|
||||
///
|
||||
/// - Parameter content: array with elements of Elemet type
|
||||
/// - Parameter content: array with elements of Element type
|
||||
public init(content: [Element]) {
|
||||
self.content = content
|
||||
}
|
||||
|
|
@ -46,10 +46,10 @@ public class StaticCursor<Element>: ResettableCursorType {
|
|||
return content[index]
|
||||
}
|
||||
|
||||
public func loadNextBatch() -> Observable<[Element]> {
|
||||
return Observable.deferred {
|
||||
public func loadNextBatch() -> Single<[Element]> {
|
||||
return Single.deferred {
|
||||
if self.exhausted {
|
||||
throw CursorError.exhausted
|
||||
return .error(CursorError.exhausted)
|
||||
}
|
||||
|
||||
self.count = self.content.count
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ where Delegate.Cursor == Cursor {
|
|||
retryButton.frame = CGRect(x: 0, y: 0, width: tableView.bounds.width, height: retryButtonHeigth)
|
||||
|
||||
retryButton.rx.controlEvent(.touchUpInside)
|
||||
.bindNext { [weak self] in
|
||||
.bind { [weak self] in
|
||||
self?.paginationViewModel.load(.next)
|
||||
}
|
||||
.addDisposableTo(disposeBag)
|
||||
|
|
@ -274,7 +274,7 @@ where Delegate.Cursor == Cursor {
|
|||
private func createRefreshControl() {
|
||||
let refreshControl = UIRefreshControl()
|
||||
refreshControl.rx.controlEvent(.valueChanged)
|
||||
.bindNext { [weak self] in
|
||||
.bind { [weak self] in
|
||||
self?.reload()
|
||||
}
|
||||
.addDisposableTo(disposeBag)
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ public final class PaginationViewModel<C: ResettableCursorType> {
|
|||
|
||||
currentRequest = currentCursor.loadNextBatch()
|
||||
.subscribeOn(internalScheduler)
|
||||
.subscribe(onNext: { [weak self] newItems in
|
||||
.subscribe(onSuccess: { [weak self] newItems in
|
||||
self?.onGot(newItems: newItems, using: currentCursor)
|
||||
}, onError: { [weak self] error in
|
||||
self?.onGot(error: error)
|
||||
|
|
|
|||
|
|
@ -53,18 +53,8 @@ open class NetworkService {
|
|||
public func rxRequest<T: ObservableMappable>(with parameters: ApiRequestParameters)
|
||||
-> Observable<(response: HTTPURLResponse, model: T)> where T.ModelType == T {
|
||||
|
||||
let responseObservable = sessionManager.rx.responseObservableModel(requestParameters: parameters)
|
||||
.counterTracking(for: self) as Observable<(response: HTTPURLResponse, model: T)>
|
||||
|
||||
#if os(iOS)
|
||||
#if LEADKIT_EXTENSION_TARGET
|
||||
return responseObservable
|
||||
#else
|
||||
return responseObservable.showErrorsInToastInDebugMode()
|
||||
#endif
|
||||
#else
|
||||
return responseObservable
|
||||
#endif
|
||||
return sessionManager.rx.responseObservableModel(requestParameters: parameters)
|
||||
.counterTracking(for: self)
|
||||
}
|
||||
|
||||
/// Perform reactive request to get mapped ImmutableMappable model and http response
|
||||
|
|
@ -74,18 +64,8 @@ open class NetworkService {
|
|||
public func rxRequest<T: ImmutableMappable>(with parameters: ApiRequestParameters)
|
||||
-> Observable<(response: HTTPURLResponse, model: T)> {
|
||||
|
||||
let responseObservable = sessionManager.rx.responseModel(requestParameters: parameters)
|
||||
.counterTracking(for: self) as Observable<(response: HTTPURLResponse, model: T)>
|
||||
|
||||
#if os(iOS)
|
||||
#if LEADKIT_EXTENSION_TARGET
|
||||
return responseObservable
|
||||
#else
|
||||
return responseObservable.showErrorsInToastInDebugMode()
|
||||
#endif
|
||||
#else
|
||||
return responseObservable
|
||||
#endif
|
||||
return sessionManager.rx.responseModel(requestParameters: parameters)
|
||||
.counterTracking(for: self)
|
||||
}
|
||||
|
||||
fileprivate func increaseRequestCounter() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,143 @@
|
|||
//
|
||||
// Copyright (c) 2017 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
|
||||
|
||||
class SpinnerView: UIView, Animatable, LoadingIndicator {
|
||||
|
||||
private(set) var animating: Bool = false
|
||||
private var startTime = CFTimeInterval(0)
|
||||
private var stopTime = CFTimeInterval(0)
|
||||
|
||||
private weak var imageView: UIImageView?
|
||||
|
||||
private let animationDuration: CFTimeInterval
|
||||
private let animationRepeatCount: Float
|
||||
private let clockwiseAnimation: Bool
|
||||
|
||||
init(image: UIImage,
|
||||
animationDuration: CFTimeInterval = 1,
|
||||
animationRepeatCount: Float = Float.infinity,
|
||||
clockwiseAnimation: Bool = true) {
|
||||
|
||||
self.animationDuration = animationDuration
|
||||
self.animationRepeatCount = animationRepeatCount
|
||||
self.clockwiseAnimation = clockwiseAnimation
|
||||
|
||||
super.init(frame: CGRect(origin: .zero, size: image.size))
|
||||
|
||||
let imageView = UIImageView(image: image)
|
||||
imageView.frame = bounds
|
||||
imageView.autoresizingMask = [
|
||||
.flexibleLeftMargin,
|
||||
.flexibleRightMargin,
|
||||
.flexibleTopMargin,
|
||||
.flexibleBottomMargin
|
||||
]
|
||||
|
||||
addSubview(imageView)
|
||||
|
||||
self.imageView = imageView
|
||||
|
||||
NotificationCenter.default.addObserver(self,
|
||||
selector: #selector(SpinnerView.restartAnimationIfNeeded),
|
||||
name: .UIApplicationWillEnterForeground,
|
||||
object: nil)
|
||||
}
|
||||
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
override func didMoveToWindow() {
|
||||
super.didMoveToWindow()
|
||||
|
||||
if window != nil {
|
||||
restartAnimationIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Animatable
|
||||
|
||||
func startAnimating() {
|
||||
guard !animating else {
|
||||
return
|
||||
}
|
||||
|
||||
animating = true
|
||||
|
||||
imageView?.isHidden = false
|
||||
|
||||
addAnimation()
|
||||
}
|
||||
|
||||
func stopAnimating() {
|
||||
guard animating else {
|
||||
return
|
||||
}
|
||||
|
||||
animating = false
|
||||
|
||||
imageView?.isHidden = true
|
||||
|
||||
removeAnimation()
|
||||
}
|
||||
|
||||
// MARK: private stuff
|
||||
|
||||
private func addAnimation() {
|
||||
guard let imageView = imageView else {
|
||||
return
|
||||
}
|
||||
|
||||
let anim = CABasicAnimation.zRotationAnimationWith(duration: animationDuration,
|
||||
repeatCount: animationRepeatCount,
|
||||
clockwise: clockwiseAnimation)
|
||||
anim.timeOffset = stopTime - startTime
|
||||
|
||||
imageView.layer.add(anim, forKey: CABasicAnimation.rotationKeyPath)
|
||||
|
||||
startTime = imageView.layer.convertTime(CACurrentMediaTime(), from: nil)
|
||||
}
|
||||
|
||||
private func removeAnimation() {
|
||||
guard let imageView = imageView else {
|
||||
return
|
||||
}
|
||||
|
||||
imageView.layer.removeAnimation(forKey: CABasicAnimation.rotationKeyPath)
|
||||
|
||||
stopTime = imageView.layer.convertTime(CACurrentMediaTime(), from: nil)
|
||||
}
|
||||
|
||||
@objc private func restartAnimationIfNeeded() {
|
||||
if animating {
|
||||
removeAnimation()
|
||||
addAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright (c) 2017 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
|
||||
// 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
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
// 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
|
||||
// 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
|
||||
|
|
@ -20,24 +20,24 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import RxSwift
|
||||
import Toast_Swift
|
||||
import QuartzCore
|
||||
|
||||
public extension Observable {
|
||||
extension CABasicAnimation {
|
||||
|
||||
/// Method which shows toast with localized description of error in DEBUG mode
|
||||
///
|
||||
/// - Returns: The source sequence with the side-effecting behavior applied.
|
||||
func showErrorsInToastInDebugMode() -> Observable<Observable.E> {
|
||||
#if DEBUG
|
||||
return `do`(onError: { (error) in
|
||||
DispatchQueue.main.async {
|
||||
UIApplication.shared.keyWindow?.makeToast(error.localizedDescription)
|
||||
}
|
||||
})
|
||||
#else
|
||||
return self
|
||||
#endif
|
||||
static let rotationKeyPath = "transform.rotation.z"
|
||||
|
||||
static func zRotationAnimationWith(duration: CFTimeInterval = 1,
|
||||
repeatCount: Float = Float.infinity,
|
||||
clockwise: Bool = true) -> CABasicAnimation {
|
||||
|
||||
let animation = CABasicAnimation(keyPath: CABasicAnimation.rotationKeyPath)
|
||||
let direction = clockwise ? 1.0 : -1.0
|
||||
animation.toValue = NSNumber(value: .pi * 2 * direction)
|
||||
animation.duration = duration
|
||||
animation.isCumulative = true
|
||||
animation.repeatCount = repeatCount
|
||||
|
||||
return animation
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -32,22 +32,12 @@ public extension NetworkService {
|
|||
public func rxLoadImage(url: String) -> Observable<(HTTPURLResponse, UIImage?)> {
|
||||
let request = RxAlamofire.requestData(.get, url, headers: [:])
|
||||
|
||||
let requestObservable = request
|
||||
return request
|
||||
.observeOn(ConcurrentDispatchQueueScheduler(qos: .background))
|
||||
.map { (response, data) -> (HTTPURLResponse, UIImage?) in
|
||||
(response, UIImage(data: data))
|
||||
}
|
||||
.counterTracking(for: self)
|
||||
|
||||
#if os(iOS)
|
||||
#if LEADKIT_EXTENSION_TARGET
|
||||
return requestObservable
|
||||
#else
|
||||
return requestObservable.showErrorsInToastInDebugMode()
|
||||
#endif
|
||||
#else
|
||||
return requestObservable
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// Copyright (c) 2017 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
|
||||
|
||||
public extension UIImage {
|
||||
|
||||
/// Creates AnyLoadingIndicator that rotates as spinner around Z axis.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - animationDuration: Duration of one full 360 degrees rotation. One second is default.
|
||||
/// - animationRepeatCount: How many times the spin should be done. If not provided, the view will spin forever.
|
||||
/// - clockwiseAnimation: Direction of the rotation. Default is clockwise (true).
|
||||
/// - Returns: Instance of AnyLoadingIndicator.
|
||||
func asSpinner(animationDuration: CFTimeInterval = 1,
|
||||
animationRepeatCount: Float = Float.infinity,
|
||||
clockwiseAnimation: Bool = true) -> AnyLoadingIndicator {
|
||||
|
||||
let spinner = SpinnerView(image: self,
|
||||
animationDuration: animationDuration,
|
||||
animationRepeatCount: animationRepeatCount,
|
||||
clockwiseAnimation: clockwiseAnimation)
|
||||
|
||||
return AnyLoadingIndicator(spinner)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -24,8 +24,6 @@ import UIKit
|
|||
|
||||
public extension UIView {
|
||||
|
||||
private static let rotationKeyPath = "transform.rotation.z"
|
||||
|
||||
/**
|
||||
Starts rotating the view around Z axis.
|
||||
|
||||
|
|
@ -34,18 +32,15 @@ public extension UIView {
|
|||
- parameter clockwise: Direction of the rotation. Default is clockwise (true).
|
||||
*/
|
||||
public func startZRotation(duration: CFTimeInterval = 1, repeatCount: Float = Float.infinity, clockwise: Bool = true) {
|
||||
let animation = CABasicAnimation(keyPath: UIView.rotationKeyPath)
|
||||
let direction = clockwise ? 1.0 : -1.0
|
||||
animation.toValue = NSNumber(value: .pi * 2 * direction)
|
||||
animation.duration = duration
|
||||
animation.isCumulative = true
|
||||
animation.repeatCount = repeatCount
|
||||
layer.add(animation, forKey: UIView.rotationKeyPath)
|
||||
let animation = CABasicAnimation.zRotationAnimationWith(duration: duration,
|
||||
repeatCount: repeatCount,
|
||||
clockwise: clockwise)
|
||||
layer.add(animation, forKey: CABasicAnimation.rotationKeyPath)
|
||||
}
|
||||
|
||||
/// Stop rotating the view around Z axis.
|
||||
public func stopZRotation() {
|
||||
layer.removeAnimation(forKey: UIView.rotationKeyPath)
|
||||
layer.removeAnimation(forKey: CABasicAnimation.rotationKeyPath)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,6 @@ public protocol CursorType {
|
|||
/// Loads next batch of results
|
||||
///
|
||||
/// - Returns: Observable of LoadResultType
|
||||
func loadNextBatch() -> Observable<[Element]>
|
||||
func loadNextBatch() -> Single<[Element]>
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class CursorTests: XCTestCase {
|
|||
let cursorExpectation = expectation(description: "Stub cursor expectation")
|
||||
|
||||
entityCursor.loadNextBatch()
|
||||
.subscribe(onNext: { _ in
|
||||
.subscribe(onSuccess: { _ in
|
||||
cursorExpectation.fulfill()
|
||||
})
|
||||
.addDisposableTo(disposeBag)
|
||||
|
|
@ -55,29 +55,15 @@ class CursorTests: XCTestCase {
|
|||
let fixedPageCursor = FixedPageCursor(cursor: stubCursor, pageSize: 16)
|
||||
|
||||
let cursorExpectation = expectation(description: "Fixed page cursor expectation")
|
||||
let cursorExpectationError = expectation(description: "Fixed page cursor error expectation")
|
||||
|
||||
fixedPageCursor.loadNextBatch()
|
||||
.subscribe(onNext: { loadedItems in
|
||||
.subscribe(onSuccess: { loadedItems in
|
||||
XCTAssertEqual(loadedItems.count, 15)
|
||||
|
||||
cursorExpectation.fulfill()
|
||||
})
|
||||
.addDisposableTo(disposeBag)
|
||||
|
||||
fixedPageCursor.loadNextBatch()
|
||||
.subscribe(onNext: { _ in
|
||||
XCTFail("Cursor should be exhausted!")
|
||||
}, onError: { error in
|
||||
switch try? cast(error) as CursorError {
|
||||
case .exhausted?:
|
||||
cursorExpectationError.fulfill()
|
||||
default:
|
||||
XCTFail("Cursor should be exhausted!")
|
||||
}
|
||||
})
|
||||
.addDisposableTo(disposeBag)
|
||||
|
||||
waitForExpectations(timeout: 10, handler: nil)
|
||||
}
|
||||
|
||||
|
|
@ -89,7 +75,7 @@ class CursorTests: XCTestCase {
|
|||
let cursorExpectation = expectation(description: "Fixed page cursor expectation")
|
||||
|
||||
fixedPageCursor.loadNextBatch()
|
||||
.subscribe(onNext: { loadedItems in
|
||||
.subscribe(onSuccess: { loadedItems in
|
||||
XCTAssertEqual(loadedItems.count, 8)
|
||||
|
||||
cursorExpectation.fulfill()
|
||||
|
|
|
|||
|
|
@ -55,10 +55,10 @@ class StubCursor: ResettableCursorType {
|
|||
self.requestDelay = other.requestDelay
|
||||
}
|
||||
|
||||
func loadNextBatch() -> Observable<[Post]> {
|
||||
return Observable.create { observer -> Disposable in
|
||||
func loadNextBatch() -> Single<[Post]> {
|
||||
return Single.create { observer -> Disposable in
|
||||
if self.exhausted {
|
||||
observer.onError(CursorError.exhausted)
|
||||
observer(.error(CursorError.exhausted))
|
||||
} else {
|
||||
DispatchQueue.global().asyncAfter(deadline: .now() + self.requestDelay, execute: {
|
||||
let countBefore = self.count
|
||||
|
|
@ -69,8 +69,7 @@ class StubCursor: ResettableCursorType {
|
|||
|
||||
self.posts = Array((self.posts + newPosts)[0..<maxNewPosts])
|
||||
|
||||
observer.onNext(self[countBefore..<self.count])
|
||||
observer.onCompleted()
|
||||
observer(.success(self[countBefore..<self.count]))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue