Replacing IHProgressHUD with PKHUD
@ -46,10 +46,6 @@
|
||||
7A3F07AB24360DC800E59687 /* Dated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F07AA24360DC800E59687 /* Dated.swift */; };
|
||||
7A3F07AD2436350B00E59687 /* SearchController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F07AC2436350B00E59687 /* SearchController.swift */; };
|
||||
7A43F9F8246C8A6200BA5B49 /* JWT.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A43F9F7246C8A6200BA5B49 /* JWT.swift */; };
|
||||
7A488C3C24A74B990054D0B2 /* RxTableViewRealmDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A488C3824A74B990054D0B2 /* RxTableViewRealmDataSource.swift */; };
|
||||
7A488C3D24A74B990054D0B2 /* RxCollectionViewRealmDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A488C3924A74B990054D0B2 /* RxCollectionViewRealmDataSource.swift */; };
|
||||
7A488C3E24A74B990054D0B2 /* Reactive+RxRealmDataSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A488C3A24A74B990054D0B2 /* Reactive+RxRealmDataSources.swift */; };
|
||||
7A488C3F24A74B990054D0B2 /* RealmBindObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A488C3B24A74B990054D0B2 /* RealmBindObserver.swift */; };
|
||||
7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7924001D3300CBFE6E /* CheckController.swift */; };
|
||||
7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */; };
|
||||
7A530B802401803A00CBFE6E /* Vehicle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7F2401803A00CBFE6E /* Vehicle.swift */; };
|
||||
@ -58,12 +54,6 @@
|
||||
7A64AE742469DFB600ABE48E /* MediaContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE702469DFB600ABE48E /* MediaContentView.swift */; };
|
||||
7A64AE752469DFB600ABE48E /* MediaBrowserViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE712469DFB600ABE48E /* MediaBrowserViewController.swift */; };
|
||||
7A64AE762469DFB600ABE48E /* ContentTransformers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE722469DFB600ABE48E /* ContentTransformers.swift */; };
|
||||
7A64AE7E2469E16100ABE48E /* RadialGradientLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE782469E16100ABE48E /* RadialGradientLayer.swift */; };
|
||||
7A64AE7F2469E16100ABE48E /* IndefiniteAnimatedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE792469E16100ABE48E /* IndefiniteAnimatedView.swift */; };
|
||||
7A64AE802469E16100ABE48E /* .gitkeep in Resources */ = {isa = PBXBuildFile; fileRef = 7A64AE7A2469E16100ABE48E /* .gitkeep */; };
|
||||
7A64AE812469E16100ABE48E /* ProgressAnimatedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE7B2469E16100ABE48E /* ProgressAnimatedView.swift */; };
|
||||
7A64AE822469E16100ABE48E /* IHProgressHUD.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE7C2469E16100ABE48E /* IHProgressHUD.swift */; };
|
||||
7A64AE832469E16100ABE48E /* IHProgressHUD.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 7A64AE7D2469E16100ABE48E /* IHProgressHUD.bundle */; };
|
||||
7A659B5924A2B1BA0043A0F2 /* AudioRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A659B5824A2B1BA0043A0F2 /* AudioRecord.swift */; };
|
||||
7A659B5B24A3768A0043A0F2 /* Substrings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A659B5A24A3768A0043A0F2 /* Substrings.swift */; };
|
||||
7A6DD903242BF4A5009DE740 /* PlateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6DD902242BF4A5009DE740 /* PlateView.swift */; };
|
||||
@ -89,6 +79,7 @@
|
||||
7A96AE31246B2FE400297C33 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A96AE30246B2FE400297C33 /* Constants.swift */; };
|
||||
7A96AE33246C095700297C33 /* Base64FS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A96AE32246C095700297C33 /* Base64FS.swift */; };
|
||||
7A9FEEC82529AB23001CA50E /* RxRealmDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FEEC72529AB23001CA50E /* RxRealmDataSource.swift */; };
|
||||
7AABDE1D2532F3EB0041AFC6 /* PKHUD in Frameworks */ = {isa = PBXBuildFile; productRef = 7AABDE1C2532F3EB0041AFC6 /* PKHUD */; };
|
||||
7AAE6AD324CDDF950023860B /* VehicleEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAE6AD224CDDF950023860B /* VehicleEvent.swift */; };
|
||||
7AB562BA249C9E9B00473D53 /* Region.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB562B9249C9E9B00473D53 /* Region.swift */; };
|
||||
7AB67E8C2435C38700258F61 /* CustomTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB67E8B2435C38700258F61 /* CustomTextField.swift */; };
|
||||
@ -145,10 +136,6 @@
|
||||
7A3F07AA24360DC800E59687 /* Dated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dated.swift; sourceTree = "<group>"; };
|
||||
7A3F07AC2436350B00E59687 /* SearchController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchController.swift; sourceTree = "<group>"; };
|
||||
7A43F9F7246C8A6200BA5B49 /* JWT.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWT.swift; sourceTree = "<group>"; };
|
||||
7A488C3824A74B990054D0B2 /* RxTableViewRealmDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxTableViewRealmDataSource.swift; sourceTree = "<group>"; };
|
||||
7A488C3924A74B990054D0B2 /* RxCollectionViewRealmDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxCollectionViewRealmDataSource.swift; sourceTree = "<group>"; };
|
||||
7A488C3A24A74B990054D0B2 /* Reactive+RxRealmDataSources.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Reactive+RxRealmDataSources.swift"; sourceTree = "<group>"; };
|
||||
7A488C3B24A74B990054D0B2 /* RealmBindObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmBindObserver.swift; sourceTree = "<group>"; };
|
||||
7A530B7924001D3300CBFE6E /* CheckController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckController.swift; sourceTree = "<group>"; };
|
||||
7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleCell.swift; sourceTree = "<group>"; };
|
||||
7A530B7F2401803A00CBFE6E /* Vehicle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Vehicle.swift; sourceTree = "<group>"; };
|
||||
@ -157,12 +144,6 @@
|
||||
7A64AE702469DFB600ABE48E /* MediaContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaContentView.swift; sourceTree = "<group>"; };
|
||||
7A64AE712469DFB600ABE48E /* MediaBrowserViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaBrowserViewController.swift; sourceTree = "<group>"; };
|
||||
7A64AE722469DFB600ABE48E /* ContentTransformers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentTransformers.swift; sourceTree = "<group>"; };
|
||||
7A64AE782469E16100ABE48E /* RadialGradientLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadialGradientLayer.swift; sourceTree = "<group>"; };
|
||||
7A64AE792469E16100ABE48E /* IndefiniteAnimatedView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IndefiniteAnimatedView.swift; sourceTree = "<group>"; };
|
||||
7A64AE7A2469E16100ABE48E /* .gitkeep */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = .gitkeep; sourceTree = "<group>"; };
|
||||
7A64AE7B2469E16100ABE48E /* ProgressAnimatedView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgressAnimatedView.swift; sourceTree = "<group>"; };
|
||||
7A64AE7C2469E16100ABE48E /* IHProgressHUD.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IHProgressHUD.swift; sourceTree = "<group>"; };
|
||||
7A64AE7D2469E16100ABE48E /* IHProgressHUD.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = IHProgressHUD.bundle; sourceTree = "<group>"; };
|
||||
7A659B5824A2B1BA0043A0F2 /* AudioRecord.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecord.swift; sourceTree = "<group>"; };
|
||||
7A659B5A24A3768A0043A0F2 /* Substrings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Substrings.swift; sourceTree = "<group>"; };
|
||||
7A6DD902242BF4A5009DE740 /* PlateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlateView.swift; sourceTree = "<group>"; };
|
||||
@ -223,6 +204,7 @@
|
||||
7A96AE2A246AFD6200297C33 /* Eureka in Frameworks */,
|
||||
7A051611241412CA00FC55AC /* SwiftDate in Frameworks */,
|
||||
7A11472323FEA18700B424AF /* RxBlocking in Frameworks */,
|
||||
7AABDE1D2532F3EB0041AFC6 /* PKHUD in Frameworks */,
|
||||
7A530B8B240181F500CBFE6E /* RxRealm in Frameworks */,
|
||||
7A11471F23FEA18700B424AF /* RxRelay in Frameworks */,
|
||||
7AF58D2F24029C5200CE01A0 /* MagazineLayout in Frameworks */,
|
||||
@ -295,8 +277,6 @@
|
||||
7A11472C23FECA3E00B424AF /* ThirdParty */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7A488C3724A74B990054D0B2 /* RxRealmDataSources */,
|
||||
7A64AE772469E16100ABE48E /* IHProgressHUD */,
|
||||
7A64AE6E2469DFB600ABE48E /* ATGMediaBrowser */,
|
||||
7A6DD90724329144009DE740 /* CenterTextLayer.swift */,
|
||||
7A96AE32246C095700297C33 /* Base64FS.swift */,
|
||||
@ -366,17 +346,6 @@
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7A488C3724A74B990054D0B2 /* RxRealmDataSources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7A488C3824A74B990054D0B2 /* RxTableViewRealmDataSource.swift */,
|
||||
7A488C3924A74B990054D0B2 /* RxCollectionViewRealmDataSource.swift */,
|
||||
7A488C3A24A74B990054D0B2 /* Reactive+RxRealmDataSources.swift */,
|
||||
7A488C3B24A74B990054D0B2 /* RealmBindObserver.swift */,
|
||||
);
|
||||
path = RxRealmDataSources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7A530B7C24017FBE00CBFE6E /* Cells */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -404,19 +373,6 @@
|
||||
path = ATGMediaBrowser;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7A64AE772469E16100ABE48E /* IHProgressHUD */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7A64AE782469E16100ABE48E /* RadialGradientLayer.swift */,
|
||||
7A64AE792469E16100ABE48E /* IndefiniteAnimatedView.swift */,
|
||||
7A64AE7A2469E16100ABE48E /* .gitkeep */,
|
||||
7A64AE7B2469E16100ABE48E /* ProgressAnimatedView.swift */,
|
||||
7A64AE7C2469E16100ABE48E /* IHProgressHUD.swift */,
|
||||
7A64AE7D2469E16100ABE48E /* IHProgressHUD.bundle */,
|
||||
);
|
||||
path = IHProgressHUD;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7A6DD901242BF48D009DE740 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -484,6 +440,7 @@
|
||||
7A0516172414EC1200FC55AC /* RxDataSources */,
|
||||
7A96AE29246AFD6200297C33 /* Eureka */,
|
||||
7A813DC02508C4D900CC93B9 /* ExceptionCatcher */,
|
||||
7AABDE1C2532F3EB0041AFC6 /* PKHUD */,
|
||||
);
|
||||
productName = AutoCat;
|
||||
productReference = 7A1146FD23FDE7E500B424AF /* AutoCat.app */;
|
||||
@ -523,6 +480,7 @@
|
||||
7A0516142414EC1200FC55AC /* XCRemoteSwiftPackageReference "RxDataSources" */,
|
||||
7A96AE28246AFD6200297C33 /* XCRemoteSwiftPackageReference "Eureka" */,
|
||||
7A813DBF2508C4D900CC93B9 /* XCRemoteSwiftPackageReference "ExceptionCatcher" */,
|
||||
7AABDE1B2532F3EB0041AFC6 /* XCRemoteSwiftPackageReference "PKHUD" */,
|
||||
);
|
||||
productRefGroup = 7A1146FE23FDE7E500B424AF /* Products */;
|
||||
projectDirPath = "";
|
||||
@ -542,10 +500,8 @@
|
||||
7A7547DE2403180A004E8406 /* SectionHeader.xib in Resources */,
|
||||
7A11470D23FDE7E600B424AF /* LaunchScreen.storyboard in Resources */,
|
||||
7A6DD90A24329541009DE740 /* RoadNumbers2.0.otf in Resources */,
|
||||
7A64AE802469E16100ABE48E /* .gitkeep in Resources */,
|
||||
7A11470A23FDE7E600B424AF /* Assets.xcassets in Resources */,
|
||||
7A11470823FDE7E500B424AF /* Main.storyboard in Resources */,
|
||||
7A64AE832469E16100ABE48E /* IHProgressHUD.bundle in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -560,7 +516,6 @@
|
||||
7A96AE33246C095700297C33 /* Base64FS.swift in Sources */,
|
||||
7A530B802401803A00CBFE6E /* Vehicle.swift in Sources */,
|
||||
7A96AE31246B2FE400297C33 /* Constants.swift in Sources */,
|
||||
7A64AE822469E16100ABE48E /* IHProgressHUD.swift in Sources */,
|
||||
7A11470123FDE7E500B424AF /* AppDelegate.swift in Sources */,
|
||||
7ADF6C9D250FA96000F237B2 /* SwiftMaskTextfield.swift in Sources */,
|
||||
7A27ADF924A09CAD0035F39E /* CocoaError.swift in Sources */,
|
||||
@ -570,7 +525,6 @@
|
||||
7A3F07AD2436350B00E59687 /* SearchController.swift in Sources */,
|
||||
7AB562BA249C9E9B00473D53 /* Region.swift in Sources */,
|
||||
7A659B5924A2B1BA0043A0F2 /* AudioRecord.swift in Sources */,
|
||||
7A488C3C24A74B990054D0B2 /* RxTableViewRealmDataSource.swift in Sources */,
|
||||
7A6DD90C24335A6D009DE740 /* FlagLayer.swift in Sources */,
|
||||
7AE26A3524F31B0700625033 /* EventsController.swift in Sources */,
|
||||
7AB67E8C2435C38700258F61 /* CustomTextField.swift in Sources */,
|
||||
@ -590,8 +544,6 @@
|
||||
7A11474923FF2B2D00B424AF /* Response.swift in Sources */,
|
||||
7A64AE762469DFB600ABE48E /* ContentTransformers.swift in Sources */,
|
||||
7A11471823FDEBFA00B424AF /* ReportController.swift in Sources */,
|
||||
7A64AE7E2469E16100ABE48E /* RadialGradientLayer.swift in Sources */,
|
||||
7A64AE7F2469E16100ABE48E /* IndefiniteAnimatedView.swift in Sources */,
|
||||
7AE24C5F251F1B4E00758E39 /* Buttons.swift in Sources */,
|
||||
7A11471A23FE839000B424AF /* AuthController.swift in Sources */,
|
||||
7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */,
|
||||
@ -610,18 +562,15 @@
|
||||
7A43F9F8246C8A6200BA5B49 /* JWT.swift in Sources */,
|
||||
7A6DD903242BF4A5009DE740 /* PlateView.swift in Sources */,
|
||||
7ADF6C9F251201D200F237B2 /* GlobalEventsController.swift in Sources */,
|
||||
7A488C3F24A74B990054D0B2 /* RealmBindObserver.swift in Sources */,
|
||||
7AAE6AD324CDDF950023860B /* VehicleEvent.swift in Sources */,
|
||||
7A11470323FDE7E500B424AF /* SceneDelegate.swift in Sources */,
|
||||
7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */,
|
||||
7A813DCB250B5DC900CC93B9 /* LocationPickerController.swift in Sources */,
|
||||
7A11474423FF06CA00B424AF /* Api.swift in Sources */,
|
||||
7A488C3D24A74B990054D0B2 /* RxCollectionViewRealmDataSource.swift in Sources */,
|
||||
7A9FEEC82529AB23001CA50E /* RxRealmDataSource.swift in Sources */,
|
||||
7AB67E8E2435D1A000258F61 /* CustomButton.swift in Sources */,
|
||||
7A21112A24FC3D7E003BBF6F /* AudioEngine.swift in Sources */,
|
||||
7A8A220B248D67B60073DFD9 /* VehicleReportImage.swift in Sources */,
|
||||
7A488C3E24A74B990054D0B2 /* Reactive+RxRealmDataSources.swift in Sources */,
|
||||
7ADF6C95250D037700F237B2 /* ShowEventController.swift in Sources */,
|
||||
7A27ADC7249D43210035F39E /* RegionsController.swift in Sources */,
|
||||
7A05161A2414FF0900FC55AC /* DateSection.swift in Sources */,
|
||||
@ -630,7 +579,6 @@
|
||||
7ADF6C93250B954900F237B2 /* Navigation.swift in Sources */,
|
||||
7A64AE752469DFB600ABE48E /* MediaBrowserViewController.swift in Sources */,
|
||||
7A64AE732469DFB600ABE48E /* DismissAnimationController.swift in Sources */,
|
||||
7A64AE812469E16100ABE48E /* ProgressAnimatedView.swift in Sources */,
|
||||
7ADF6C97250F41B000F237B2 /* PNKeyboard.swift in Sources */,
|
||||
7A000AA224C2EEDE001F5B00 /* Location.swift in Sources */,
|
||||
7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */,
|
||||
@ -897,6 +845,14 @@
|
||||
minimumVersion = 5.2.1;
|
||||
};
|
||||
};
|
||||
7AABDE1B2532F3EB0041AFC6 /* XCRemoteSwiftPackageReference "PKHUD" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/pkluz/PKHUD.git";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 5.4.0;
|
||||
};
|
||||
};
|
||||
7AF58D2D24029C5200CE01A0 /* XCRemoteSwiftPackageReference "MagazineLayout" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/airbnb/MagazineLayout";
|
||||
@ -976,6 +932,11 @@
|
||||
package = 7A96AE28246AFD6200297C33 /* XCRemoteSwiftPackageReference "Eureka" */;
|
||||
productName = Eureka;
|
||||
};
|
||||
7AABDE1C2532F3EB0041AFC6 /* PKHUD */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 7AABDE1B2532F3EB0041AFC6 /* XCRemoteSwiftPackageReference "PKHUD" */;
|
||||
productName = PKHUD;
|
||||
};
|
||||
7AF58D2E24029C5200CE01A0 /* MagazineLayout */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 7AF58D2D24029C5200CE01A0 /* XCRemoteSwiftPackageReference "MagazineLayout" */;
|
||||
|
||||
@ -37,6 +37,15 @@
|
||||
"version": "1.6.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "PKHUD",
|
||||
"repositoryURL": "https://github.com/pkluz/PKHUD.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "8fd26f23057c6bebd6695524b1c3e05e93aba571",
|
||||
"version": "5.4.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "Realm",
|
||||
"repositoryURL": "https://github.com/realm/realm-cocoa",
|
||||
|
||||
@ -3,6 +3,7 @@ import RealmSwift
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import os.log
|
||||
import PKHUD
|
||||
|
||||
extension OSLog {
|
||||
static let startup = OSLog(subsystem: "pro.aliencat.autocat.startup", category: "startup")
|
||||
@ -68,8 +69,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
Realm.Configuration.defaultConfiguration = config
|
||||
|
||||
IHProgressHUD.set(defaultStyle: .dark)
|
||||
IHProgressHUD.set(defaultMaskType: .black)
|
||||
HUD.dimsBackground = true
|
||||
HUD.allowsInteraction = false
|
||||
|
||||
Logging.URLRequests = { _ in false };
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import UIKit
|
||||
import RxSwift
|
||||
import PKHUD
|
||||
|
||||
class AudioRecordCell: UITableViewCell, ConfigurableCell {
|
||||
|
||||
@ -74,7 +75,7 @@ class AudioRecordCell: UITableViewCell, ConfigurableCell {
|
||||
try AudioPlayer.shared.play(url: url)
|
||||
} catch {
|
||||
print("Error playing audio record: \(error.localizedDescription)")
|
||||
IHProgressHUD.showError(withStatus: error.localizedDescription)
|
||||
HUD.show(error: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ import RxSwift
|
||||
import RxCocoa
|
||||
import RealmSwift
|
||||
import AuthenticationServices
|
||||
import PKHUD
|
||||
|
||||
class AuthController: UIViewController, ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding {
|
||||
|
||||
@ -35,20 +36,20 @@ class AuthController: UIViewController, ASAuthorizationControllerDelegate, ASAut
|
||||
@IBAction func loginTapped(_ sender: UIButton) {
|
||||
guard let email = self.username.text, let pass = self.password.text else { return }
|
||||
|
||||
IHProgressHUD.show()
|
||||
HUD.show(.progress)
|
||||
Api.login(email: email, password: pass)
|
||||
.observeOn(MainScheduler.instance)
|
||||
.subscribe(onSuccess: self.goToMainScreen(user:), onError: self.displayError(error:))
|
||||
.subscribe(onSuccess: self.goToMainScreen(user:), onError: HUD.show(error:))
|
||||
.disposed(by: self.bag)
|
||||
}
|
||||
|
||||
@IBAction func signupTapped(_ sender: UIButton) {
|
||||
guard let email = self.username.text, let pass = self.password.text else { return }
|
||||
|
||||
IHProgressHUD.show()
|
||||
HUD.show(.progress)
|
||||
Api.signUp(email: email, password: pass)
|
||||
.observeOn(MainScheduler.instance)
|
||||
.subscribe(onSuccess: self.goToMainScreen(user:), onError: self.displayError(error:))
|
||||
.subscribe(onSuccess: self.goToMainScreen(user:), onError: HUD.show(error:))
|
||||
.disposed(by: self.bag)
|
||||
}
|
||||
|
||||
@ -64,29 +65,24 @@ class AuthController: UIViewController, ASAuthorizationControllerDelegate, ASAut
|
||||
}
|
||||
|
||||
func goToMainScreen(user: User) {
|
||||
// guard let realm = try? Realm() else {
|
||||
// IHProgressHUD.showError(withStatus: "Database error")
|
||||
// return
|
||||
// }
|
||||
guard let realm = try? Realm() else {
|
||||
HUD.flash(.labeledError(title: nil, subtitle: "Database error"))
|
||||
return
|
||||
}
|
||||
|
||||
IHProgressHUD.dismiss()
|
||||
HUD.hide()
|
||||
|
||||
// if user.email != Settings.shared.user.email {
|
||||
// try? realm.write {
|
||||
// realm.deleteAll()
|
||||
// }
|
||||
// }
|
||||
if user.email != Settings.shared.user.email {
|
||||
try? realm.write {
|
||||
realm.deleteAll()
|
||||
}
|
||||
}
|
||||
|
||||
Settings.shared.user = user
|
||||
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
||||
self.view.window?.rootViewController = storyboard.instantiateViewController(identifier: "MainSplitController")
|
||||
}
|
||||
|
||||
func displayError(error: Error) {
|
||||
IHProgressHUD.showError(withStatus: error.localizedDescription)
|
||||
print(error)
|
||||
}
|
||||
|
||||
// MARK: - Apple SignIn
|
||||
|
||||
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
|
||||
@ -97,14 +93,14 @@ class AuthController: UIViewController, ASAuthorizationControllerDelegate, ASAut
|
||||
switch authorization.credential {
|
||||
case let appleIDCredential as ASAuthorizationAppleIDCredential:
|
||||
guard let email = appleIDCredential.email else {
|
||||
IHProgressHUD.showError(withStatus: "Cannot get email")
|
||||
HUD.flash(.labeledError(title: nil, subtitle: "Cannot get email"))
|
||||
return
|
||||
}
|
||||
|
||||
IHProgressHUD.show()
|
||||
HUD.show(.progress)
|
||||
Api.signIn(email: email, password: appleIDCredential.user)
|
||||
.observeOn(MainScheduler.instance)
|
||||
.subscribe(onSuccess: self.goToMainScreen(user:), onError: self.displayError(error:))
|
||||
.subscribe(onSuccess: self.goToMainScreen(user:), onError: HUD.show(error:))
|
||||
.disposed(by: self.bag)
|
||||
|
||||
if let tokenData = appleIDCredential.identityToken {
|
||||
@ -116,7 +112,7 @@ class AuthController: UIViewController, ASAuthorizationControllerDelegate, ASAut
|
||||
})
|
||||
}
|
||||
default:
|
||||
IHProgressHUD.showError(withStatus: "Unsupported authorization credential")
|
||||
HUD.flash(.labeledError(title: nil, subtitle: "Unsupported authorization credential"))
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ import RealmSwift
|
||||
import RxSwift
|
||||
import SwiftDate
|
||||
import RxRealm
|
||||
import PKHUD
|
||||
|
||||
enum EventAction {
|
||||
case doNotSend
|
||||
@ -99,12 +100,12 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat
|
||||
self.number.text = nil
|
||||
self.check.isEnabled = false
|
||||
|
||||
IHProgressHUD.show()
|
||||
HUD.show(.progress)
|
||||
self.check(number: numberNormalized, action: .receiveAndSend).subscribe { vehicle in
|
||||
self.updateDetailController(with: vehicle)
|
||||
IHProgressHUD.dismiss()
|
||||
HUD.hide()
|
||||
} onError: { error in
|
||||
IHProgressHUD.show(error: error)
|
||||
HUD.show(error: error)
|
||||
}
|
||||
.disposed(by: self.bag)
|
||||
|
||||
@ -198,7 +199,7 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat
|
||||
// MARK: - Contextual actions
|
||||
|
||||
func update(vehicle: Vehicle) {
|
||||
IHProgressHUD.show()
|
||||
HUD.show(.progress)
|
||||
|
||||
var eventAction: EventAction = .doNotSend
|
||||
if vehicle.unrecognized, let savedEvent = vehicle.events.first {
|
||||
@ -207,9 +208,9 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat
|
||||
|
||||
self.check(number: vehicle.getNumber(), action: eventAction, force: true).subscribe { vehicle in
|
||||
self.updateDetailController(with: vehicle)
|
||||
IHProgressHUD.dismiss()
|
||||
HUD.hide()
|
||||
} onError: { error in
|
||||
IHProgressHUD.show(error: error)
|
||||
HUD.show(error: error)
|
||||
}
|
||||
.disposed(by: self.bag)
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ import UIKit
|
||||
import WebKit
|
||||
import CommonCrypto
|
||||
import RxSwift
|
||||
import PKHUD
|
||||
|
||||
struct TokenResponse: Codable {
|
||||
var id_token: String
|
||||
@ -58,7 +59,7 @@ class GoogleSignInController: UIViewController, WKNavigationDelegate {
|
||||
.subscribe(onSuccess: { _ in
|
||||
self.dismiss(animated: true, completion: self.completion)
|
||||
}, onError: { error in
|
||||
IHProgressHUD.showError(withStatus: error.localizedDescription)
|
||||
HUD.flash(.labeledError(title: nil, subtitle: error.localizedDescription))
|
||||
})
|
||||
.disposed(by: self.bag)
|
||||
return
|
||||
|
||||
@ -3,6 +3,7 @@ import MapKit
|
||||
import RxSwift
|
||||
import Realm
|
||||
import RealmSwift
|
||||
import PKHUD
|
||||
|
||||
class EventPin: NSObject, MKAnnotation {
|
||||
var coordinate: CLLocationCoordinate2D
|
||||
@ -148,18 +149,18 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
|
||||
|
||||
func deleteEvent(index: Int, completion: @escaping (Bool) -> Void) {
|
||||
guard let vehicle = self.vehicle else {
|
||||
IHProgressHUD.showError(withStatus: "Unknown vehicle")
|
||||
HUD.flash(.labeledError(title: nil, subtitle: "Unknown vehicle"))
|
||||
return
|
||||
}
|
||||
|
||||
let event = vehicle.events[index]
|
||||
if let eventId = event.id {
|
||||
IHProgressHUD.show()
|
||||
HUD.show(.progress)
|
||||
Api.remove(event: eventId).observeOn(MainScheduler.instance).subscribe(onSuccess: { vehicle in
|
||||
completion(self.update(vehicle: vehicle))
|
||||
}, onError: { error in
|
||||
completion(false)
|
||||
IHProgressHUD.show(error: error)
|
||||
HUD.show(error: error)
|
||||
print(error)
|
||||
}).disposed(by: self.bag)
|
||||
} else {
|
||||
@ -169,7 +170,7 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
|
||||
|
||||
func editEvent(index: Int) {
|
||||
guard let vehicle = self.vehicle else {
|
||||
IHProgressHUD.showError(withStatus: "Unknown vehicle")
|
||||
HUD.flash(.labeledError(title: nil, subtitle: "Unknown vehicle"))
|
||||
return
|
||||
}
|
||||
|
||||
@ -182,12 +183,12 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
|
||||
controller.onDone = { newEvent in
|
||||
newEvent.id = event.id
|
||||
self.navigationController?.popViewController(animated: true, completion: {
|
||||
IHProgressHUD.show()
|
||||
HUD.show(.progress)
|
||||
Api.edit(event: newEvent)
|
||||
.observeOn(MainScheduler.instance)
|
||||
.subscribe(onSuccess: { self.update(vehicle: $0) }, onError:
|
||||
{ error in
|
||||
IHProgressHUD.show(error: error)
|
||||
HUD.show(error: error)
|
||||
})
|
||||
.disposed(by: self.bag)
|
||||
})
|
||||
@ -197,7 +198,7 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
|
||||
|
||||
@objc func addEvent(_ sender: UIBarButtonItem) {
|
||||
guard let vehicle = self.vehicle else {
|
||||
IHProgressHUD.showError(withStatus: "Unknown vehicle")
|
||||
HUD.flash(.labeledError(title: nil, subtitle: "Unknown vehicle"))
|
||||
return
|
||||
}
|
||||
|
||||
@ -206,12 +207,12 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
|
||||
controller.title = "Add new event"
|
||||
controller.onDone = { newEvent in
|
||||
self.navigationController?.popViewController(animated: true, completion: {
|
||||
IHProgressHUD.show()
|
||||
HUD.show(.progress)
|
||||
Api.add(event: newEvent, to: vehicle.getNumber())
|
||||
.observeOn(MainScheduler.instance)
|
||||
.subscribe(onSuccess: { self.update(vehicle: $0) }, onError:
|
||||
{ error in
|
||||
IHProgressHUD.show(error: error)
|
||||
HUD.show(error: error)
|
||||
})
|
||||
.disposed(by: self.bag)
|
||||
})
|
||||
@ -231,10 +232,10 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
|
||||
self.vehicle?.events.append(objectsIn: vehicle.events)
|
||||
}
|
||||
self.updateInterface()
|
||||
IHProgressHUD.dismiss()
|
||||
HUD.hide()
|
||||
return true
|
||||
} catch {
|
||||
IHProgressHUD.show(error: error)
|
||||
HUD.show(error: error)
|
||||
print(error)
|
||||
return false
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import UIKit
|
||||
import MapKit
|
||||
import RxSwift
|
||||
import PKHUD
|
||||
|
||||
class GlobalEventsController: UIViewController {
|
||||
|
||||
@ -16,7 +17,7 @@ class GlobalEventsController: UIViewController {
|
||||
self.map.showsZoomControls = true
|
||||
#endif
|
||||
|
||||
IHProgressHUD.show()
|
||||
HUD.show(.progress)
|
||||
Api.events(with: self.filter)
|
||||
.observeOn(MainScheduler.init())
|
||||
.subscribe(onSuccess: { events in
|
||||
@ -25,9 +26,9 @@ class GlobalEventsController: UIViewController {
|
||||
self.map.removeAnnotations(self.map.annotations)
|
||||
self.map.addAnnotations(pins)
|
||||
self.map.centerOnPins()
|
||||
IHProgressHUD.dismiss()
|
||||
HUD.hide()
|
||||
}) { error in
|
||||
IHProgressHUD.show(error: error)
|
||||
HUD.show(error: error)
|
||||
}
|
||||
.disposed(by: self.bag)
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import Intents
|
||||
import CoreSpotlight
|
||||
import MobileCoreServices
|
||||
import os.log
|
||||
import PKHUD
|
||||
|
||||
class RecordsController: UIViewController, UITableViewDelegate {
|
||||
|
||||
@ -84,7 +85,7 @@ class RecordsController: UIViewController, UITableViewDelegate {
|
||||
|
||||
@objc func onAddVoiceRecord(_ sender: UIBarButtonItem) {
|
||||
guard let recorder = self.recorder else {
|
||||
IHProgressHUD.showError(withStatus: "Audio recorder is not available")
|
||||
HUD.flash(.labeledError(title: nil, subtitle: "Audio recorder is not available"))
|
||||
return
|
||||
}
|
||||
|
||||
@ -142,10 +143,10 @@ class RecordsController: UIViewController, UITableViewDelegate {
|
||||
}) { error in
|
||||
if let alert = alert {
|
||||
alert.dismiss(animated: true) {
|
||||
IHProgressHUD.show(error: error)
|
||||
HUD.show(error: error)
|
||||
}
|
||||
} else {
|
||||
IHProgressHUD.show(error: error)
|
||||
HUD.show(error: error)
|
||||
}
|
||||
self.addButton.isEnabled = true
|
||||
}
|
||||
@ -274,7 +275,7 @@ class RecordsController: UIViewController, UITableViewDelegate {
|
||||
self.present(controller, animated: true)
|
||||
} catch {
|
||||
print("Error sharing audio record: \(error.localizedDescription)")
|
||||
IHProgressHUD.showError(withStatus: error.localizedDescription)
|
||||
HUD.show(error: error)
|
||||
}
|
||||
}
|
||||
let showText = UIAlertAction(title: "Show recognized text", style: .default) { action in
|
||||
|
||||
@ -3,6 +3,7 @@ import RxDataSources
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RealmSwift
|
||||
import PKHUD
|
||||
|
||||
class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDelegate {
|
||||
|
||||
@ -160,9 +161,9 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
|
||||
}
|
||||
|
||||
func update(vehicle: Vehicle, at indexPath: IndexPath) {
|
||||
IHProgressHUD.show()
|
||||
HUD.show(.progress)
|
||||
Api.checkVehicle(by: vehicle.getNumber(), force: true).observeOn(MainScheduler.instance).subscribe { newVehicle in
|
||||
IHProgressHUD.dismiss()
|
||||
HUD.hide()
|
||||
if let realm = try? Realm() {
|
||||
if realm.object(ofType: Vehicle.self, forPrimaryKey: vehicle.getNumber()) != nil {
|
||||
try? realm.write {
|
||||
@ -173,7 +174,7 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
|
||||
self.datasource[indexPath] = newVehicle
|
||||
self.updateDetailController(with: newVehicle)
|
||||
} onError: { err in
|
||||
IHProgressHUD.show(error: err)
|
||||
HUD.show(error: err)
|
||||
}.disposed(by: self.bag)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import UIKit
|
||||
import PKHUD
|
||||
|
||||
extension NSError {
|
||||
var displayMessage: (title: String, body: String) {
|
||||
@ -50,9 +51,9 @@ extension UIViewController {
|
||||
}
|
||||
}
|
||||
|
||||
extension IHProgressHUD {
|
||||
extension HUD {
|
||||
static func show(error: Error) {
|
||||
let msg = (error as NSError).displayMessage
|
||||
self.showError(withStatus: msg.title + "\n" + msg.body)
|
||||
self.flash(.labeledError(title: msg.title, subtitle: msg.body), delay: 2.0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ import UIKit
|
||||
import os.log
|
||||
import AVFoundation
|
||||
import RxSwift
|
||||
import PKHUD
|
||||
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
@ -145,7 +146,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
func openReport(with number: String) {
|
||||
guard let rootController = self.window?.rootViewController else { return }
|
||||
|
||||
IHProgressHUD.show()
|
||||
HUD.show(.progress)
|
||||
_ = Api.getReport(for: number).observeOn(MainScheduler.instance).subscribe { vehicle in
|
||||
let sb = UIStoryboard(name: "Main", bundle: nil)
|
||||
let controller = sb.instantiateViewController(identifier: "ReportController") as ReportController
|
||||
@ -154,9 +155,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
nav.modalPresentationStyle = .fullScreen
|
||||
controller.navigationItem.leftBarButtonItem = BlockBarButtonItem(barButtonSystemItem: .close) { _ in nav.dismiss(animated: true) }
|
||||
rootController.present(nav, animated: true)
|
||||
IHProgressHUD.dismiss()
|
||||
HUD.hide()
|
||||
} onError: { error in
|
||||
IHProgressHUD.show(error: error)
|
||||
HUD.show(error: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 409 B |
|
Before Width: | Height: | Size: 873 B |
|
Before Width: | Height: | Size: 752 B |
|
Before Width: | Height: | Size: 662 B |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 490 B |
|
Before Width: | Height: | Size: 912 B |
|
Before Width: | Height: | Size: 1.3 KiB |
1317
AutoCat/ThirdParty/IHProgressHUD/IHProgressHUD.swift
vendored
@ -1,197 +0,0 @@
|
||||
//
|
||||
// Converted to Swift 4 by Swiftify v4.2.29618 - https://objectivec2swift.com/
|
||||
//
|
||||
// IndefiniteAnimatedView.swift
|
||||
// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD
|
||||
//
|
||||
// Original Copyright (c) 2014-2018 Guillaume Campagna. All rights reserved.
|
||||
// Modified Copyright © 2018 Ibrahim Hassan. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class IndefiniteAnimatedView : UIView {
|
||||
|
||||
private var activityIndicator : UIActivityIndicatorView?
|
||||
private var strokeThickness : CGFloat?
|
||||
private var strokeColor : UIColor?
|
||||
private var indefinteAnimatedLayer : CAShapeLayer?
|
||||
private var radius : CGFloat?
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
if self.superview != nil {
|
||||
layoutAnimatedLayer()
|
||||
}
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - Setter Functions
|
||||
extension IndefiniteAnimatedView {
|
||||
|
||||
func setIndefinite(radius: CGFloat) {
|
||||
if (self.radius != radius) {
|
||||
self.radius = radius
|
||||
|
||||
self.getIndefinteAnimatedLayer().removeFromSuperlayer()
|
||||
self.indefinteAnimatedLayer = nil
|
||||
|
||||
if superview != nil {
|
||||
layoutAnimatedLayer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setIndefinite(strokeThickness : CGFloat) {
|
||||
self.strokeThickness = strokeThickness
|
||||
if let strkthickness = self.strokeThickness {
|
||||
getIndefinteAnimatedLayer().lineWidth = strkthickness
|
||||
}
|
||||
}
|
||||
|
||||
func setIndefinite(strokeColor: UIColor) {
|
||||
self.strokeColor = strokeColor
|
||||
getIndefinteAnimatedLayer().strokeColor = strokeColor.cgColor
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//MARK: - Getter Functions
|
||||
extension IndefiniteAnimatedView {
|
||||
private func getIndefinteAnimatedLayer() -> CAShapeLayer {
|
||||
if self.indefinteAnimatedLayer != nil {
|
||||
return self.indefinteAnimatedLayer!
|
||||
} else {
|
||||
let localRingRadius : CGFloat = radius ?? 18
|
||||
let localStrokeThickness : CGFloat = strokeThickness ?? 2
|
||||
let localStrokeColor : UIColor = strokeColor ?? UIColor.black
|
||||
|
||||
let arcCenter = CGPoint(x: localRingRadius + localStrokeThickness / 2 + 5, y: localRingRadius + localStrokeThickness / 2 + 5)
|
||||
let smoothedPath = UIBezierPath(arcCenter: arcCenter, radius: localRingRadius, startAngle: -CGFloat.pi / 2, endAngle: CGFloat.pi + CGFloat.pi / 2, clockwise: true)
|
||||
|
||||
indefinteAnimatedLayer = CAShapeLayer()
|
||||
indefinteAnimatedLayer?.contentsScale = UIScreen.main.scale
|
||||
indefinteAnimatedLayer?.frame = CGRect.init(x: 0, y: 0, width: arcCenter.x * 2, height: arcCenter.y * 2)
|
||||
indefinteAnimatedLayer?.fillColor = UIColor.clear.cgColor
|
||||
indefinteAnimatedLayer?.strokeColor = localStrokeColor.cgColor
|
||||
indefinteAnimatedLayer?.lineWidth = localStrokeThickness
|
||||
indefinteAnimatedLayer?.lineCap = CAShapeLayerLineCap.round
|
||||
indefinteAnimatedLayer?.lineJoin = CAShapeLayerLineJoin.bevel
|
||||
indefinteAnimatedLayer?.path = smoothedPath.cgPath
|
||||
|
||||
let maskLayer = CALayer()
|
||||
let image = loadImageBundle(named: "angle-mask")!
|
||||
maskLayer.contents = image.cgImage
|
||||
maskLayer.frame = indefinteAnimatedLayer!.bounds
|
||||
indefinteAnimatedLayer?.mask = maskLayer
|
||||
|
||||
let animationDuration = TimeInterval.init(1)
|
||||
let linearCurve = CAMediaTimingFunction.init(name: .linear)
|
||||
let animation = CABasicAnimation.init(keyPath: "transform.rotation")
|
||||
animation.fromValue = 0
|
||||
animation.toValue = CGFloat.pi * 2
|
||||
animation.duration = animationDuration
|
||||
animation.timingFunction = linearCurve
|
||||
animation.isRemovedOnCompletion = false
|
||||
animation.repeatCount = .infinity
|
||||
animation.fillMode = .forwards
|
||||
animation.autoreverses = false
|
||||
indefinteAnimatedLayer?.mask?.add(animation, forKey: "rotate")
|
||||
|
||||
|
||||
let animationGroup = CAAnimationGroup.init()
|
||||
animationGroup.duration = animationDuration
|
||||
animationGroup.repeatCount = .infinity
|
||||
animationGroup.isRemovedOnCompletion = false
|
||||
animationGroup.timingFunction = linearCurve
|
||||
|
||||
let strokeStartAnimation = CABasicAnimation.init(keyPath: "strokeStart")
|
||||
strokeStartAnimation.duration = animationDuration
|
||||
strokeStartAnimation.fromValue = 0.015
|
||||
strokeStartAnimation.toValue = 0.0001
|
||||
|
||||
animationGroup.animations = [strokeStartAnimation]
|
||||
indefinteAnimatedLayer?.add(animationGroup, forKey: "progress")
|
||||
}
|
||||
return self.indefinteAnimatedLayer!
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - ActivityIndicatorView Functions
|
||||
extension IndefiniteAnimatedView {
|
||||
|
||||
func removeAnimationLayer() {
|
||||
for view in self.subviews {
|
||||
if let activityView = view as? UIActivityIndicatorView {
|
||||
activityView.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
getIndefinteAnimatedLayer().removeFromSuperlayer()
|
||||
}
|
||||
|
||||
func startAnimation() {
|
||||
if let activityIndicator = activityIndicator {
|
||||
self.addSubview(activityIndicator)
|
||||
activityIndicator.frame = CGRect.init(x: 8, y: 8, width: self.frame.size.width - 16, height: self.frame.size.height - 16)
|
||||
}
|
||||
}
|
||||
|
||||
func stopActivityIndicator() {
|
||||
activityIndicator?.stopAnimating()
|
||||
}
|
||||
|
||||
func setActivityIndicator(color: UIColor) {
|
||||
activityIndicator = UIActivityIndicatorView.init(style: UIActivityIndicatorView.Style.large)
|
||||
activityIndicator?.hidesWhenStopped = true
|
||||
activityIndicator?.startAnimating()
|
||||
activityIndicator?.color = color
|
||||
}
|
||||
}
|
||||
//MARK: -
|
||||
extension IndefiniteAnimatedView {
|
||||
override func willMove(toSuperview newSuperview: UIView?) {
|
||||
if let _ = newSuperview {
|
||||
layoutAnimatedLayer()
|
||||
} else {
|
||||
getIndefinteAnimatedLayer().removeFromSuperlayer()
|
||||
indefinteAnimatedLayer = nil
|
||||
}
|
||||
}
|
||||
|
||||
private func layoutAnimatedLayer() {
|
||||
let calayer = getIndefinteAnimatedLayer()
|
||||
self.layer.addSublayer(calayer)
|
||||
let widthDiff: CGFloat = bounds.width - layer.bounds.width
|
||||
let heightDiff: CGFloat = bounds.height - layer.bounds.height
|
||||
let xPos = bounds.width - layer.bounds.width / 2 - widthDiff / 2
|
||||
let yPos = bounds.height - layer.bounds.height / 2 - heightDiff / 2
|
||||
calayer.position = CGPoint.init(x: xPos, y: yPos)
|
||||
}
|
||||
|
||||
override func sizeThatFits(_ size: CGSize) -> CGSize {
|
||||
let localRadius : CGFloat = radius ?? 18
|
||||
let localStrokeThickness : CGFloat = strokeThickness ?? 2
|
||||
for view in self.subviews {
|
||||
if let _ = view as? UIActivityIndicatorView {
|
||||
return CGSize.init(width: 50, height: 50)
|
||||
}
|
||||
}
|
||||
return CGSize.init(width: (localRadius + localStrokeThickness / 2 + 5) * 2, height: (localRadius + localStrokeThickness / 2 + 5) * 2)
|
||||
}
|
||||
|
||||
private func loadImageBundle(named imageName:String) -> UIImage? {
|
||||
var imageBundle = Bundle.init(for: IndefiniteAnimatedView.self)
|
||||
if let resourcePath = imageBundle.path(forResource: "IHProgressHUD", ofType: "bundle") {
|
||||
if let resourcesBundle = Bundle(path: resourcePath) {
|
||||
imageBundle = resourcesBundle
|
||||
}
|
||||
}
|
||||
|
||||
return (UIImage(named: imageName, in: imageBundle, compatibleWith: nil))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,128 +0,0 @@
|
||||
//
|
||||
// Converted to Swift 4 by Swiftify v4.2.29618 - https://objectivec2swift.com/
|
||||
//
|
||||
// IndefiniteAnimatedView.swift
|
||||
// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD
|
||||
//
|
||||
// Original Copyright (c) 2014-2018 Guillaume Campagna. All rights reserved.
|
||||
// Modified Copyright © 2018 Ibrahim Hassan. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class ProgressAnimatedView: UIView {
|
||||
|
||||
private var radius : CGFloat?
|
||||
private var strokeThickness : CGFloat?
|
||||
private var strokeColor : UIColor?
|
||||
private var strokeEnd : CGFloat?
|
||||
private var ringAnimatedLayer : CAShapeLayer?
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func willMove(toSuperview newSuperview: UIView?) {
|
||||
if let _ = newSuperview {
|
||||
layoutAnimatedLayer()
|
||||
} else {
|
||||
getRingAnimatedLayer().removeFromSuperlayer()
|
||||
ringAnimatedLayer = nil
|
||||
}
|
||||
}
|
||||
|
||||
func layoutAnimatedLayer() {
|
||||
let rlayer = getRingAnimatedLayer()
|
||||
layer.addSublayer(rlayer)
|
||||
let widthDiff = bounds.width - layer.bounds.width
|
||||
let heightDiff = bounds.height - layer.bounds.height
|
||||
let layerPositionX = bounds.width - layer.bounds.width / 2 - widthDiff / 2
|
||||
let layerPositionY = bounds.height - layer.bounds.height / 2 - heightDiff / 2
|
||||
rlayer.position = CGPoint.init(x: layerPositionX, y: layerPositionY)
|
||||
}
|
||||
|
||||
override func sizeThatFits(_ size: CGSize) -> CGSize {
|
||||
let localRadius : CGFloat = radius ?? 18
|
||||
let localStrokeThickness : CGFloat = strokeThickness ?? 2
|
||||
return CGSize(width: (localRadius + localStrokeThickness / 2 + 5) * 2, height: (localRadius + localStrokeThickness / 2 + 5) * 2)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//MARK: - Setter
|
||||
extension ProgressAnimatedView {
|
||||
@objc public func set(radius: CGFloat) {
|
||||
if radius != self.radius {
|
||||
self.radius = radius
|
||||
|
||||
getRingAnimatedLayer().removeFromSuperlayer()
|
||||
ringAnimatedLayer = nil
|
||||
|
||||
if superview != nil {
|
||||
layoutAnimatedLayer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func set(strokeThickness : CGFloat) {
|
||||
self.strokeThickness = strokeThickness
|
||||
getRingAnimatedLayer().lineWidth = strokeThickness
|
||||
|
||||
if superview != nil {
|
||||
layoutAnimatedLayer()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func set(strokeEnd: CGFloat) {
|
||||
self.strokeEnd = strokeEnd
|
||||
getRingAnimatedLayer().strokeEnd = strokeEnd
|
||||
|
||||
if superview != nil {
|
||||
layoutAnimatedLayer()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func set(strokeColor: UIColor) {
|
||||
|
||||
self.strokeColor = strokeColor
|
||||
self.getRingAnimatedLayer().strokeColor = strokeColor.cgColor
|
||||
|
||||
if superview != nil {
|
||||
layoutAnimatedLayer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - Getter
|
||||
extension ProgressAnimatedView {
|
||||
private func getRingAnimatedLayer() -> CAShapeLayer {
|
||||
if self.ringAnimatedLayer != nil {
|
||||
return self.ringAnimatedLayer!
|
||||
} else {
|
||||
let localStrokeThickness: CGFloat = strokeThickness ?? 2
|
||||
let localRingRadius: CGFloat = radius ?? 18
|
||||
|
||||
let arcCenter = CGPoint(x: localRingRadius + localStrokeThickness / 2 + 5, y: localRingRadius + localStrokeThickness / 2 + 5)
|
||||
let smoothedPath = UIBezierPath(arcCenter: arcCenter, radius: localRingRadius, startAngle: -CGFloat.pi / 2, endAngle: CGFloat.pi + CGFloat.pi / 2, clockwise: true)
|
||||
|
||||
let _ringAnimatedLayer = CAShapeLayer()
|
||||
_ringAnimatedLayer.contentsScale = UIScreen.main.scale
|
||||
_ringAnimatedLayer.frame = CGRect(x: 0.0, y: 0.0, width: arcCenter.x * 2, height: arcCenter.y * 2)
|
||||
_ringAnimatedLayer.fillColor = UIColor.clear.cgColor
|
||||
_ringAnimatedLayer.strokeColor = strokeColor?.cgColor
|
||||
_ringAnimatedLayer.lineWidth = localStrokeThickness
|
||||
_ringAnimatedLayer.lineCap = .round
|
||||
_ringAnimatedLayer.lineJoin = .bevel
|
||||
_ringAnimatedLayer.path = smoothedPath.cgPath
|
||||
self.ringAnimatedLayer = _ringAnimatedLayer
|
||||
}
|
||||
return self.ringAnimatedLayer!
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
//
|
||||
// Converted to Swift 4 by Swiftify v4.2.29618 - https://objectivec2swift.com/
|
||||
//
|
||||
// IndefiniteAnimatedView.swift
|
||||
// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD
|
||||
//
|
||||
// Original Copyright (c) 2014-2018 Guillaume Campagna. All rights reserved.
|
||||
// Modified Copyright © 2018 Ibrahim Hassan. All rights reserved.
|
||||
//
|
||||
|
||||
import QuartzCore
|
||||
|
||||
class RadialGradientLayer: CALayer {
|
||||
var gradientCenter = CGPoint.zero
|
||||
override func draw(in context: CGContext) {
|
||||
super.draw(in: context)
|
||||
let locationsCount = 2
|
||||
let locations : [CGFloat] = [0.0, 1.0]
|
||||
let colors : [CGFloat] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.75]
|
||||
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
||||
if let gradient = CGGradient.init(colorSpace: colorSpace, colorComponents: colors, locations: locations, count: locationsCount) {
|
||||
let radius = min(bounds.size.width, bounds.size.height)
|
||||
|
||||
context.drawRadialGradient(gradient, startCenter: gradientCenter, startRadius: 0, endCenter: gradientCenter, endRadius: radius, options: CGGradientDrawingOptions.drawsAfterEndLocation)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,113 +0,0 @@
|
||||
//
|
||||
// RxRealm extensions
|
||||
//
|
||||
// Copyright (c) 2016 RxSwiftCommunity. All rights reserved.
|
||||
// Check the LICENSE file for details
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
import RealmSwift
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxRealm
|
||||
|
||||
#if os(iOS)
|
||||
// MARK: - iOS / UIKit
|
||||
|
||||
import UIKit
|
||||
extension Reactive where Base: UITableView {
|
||||
|
||||
public func realmChanges<E>(_ dataSource: RxTableViewRealmDataSource<E>)
|
||||
-> RealmBindObserver<E, AnyRealmCollection<E>, RxTableViewRealmDataSource<E>> {
|
||||
|
||||
return RealmBindObserver(dataSource: dataSource) {ds, results, changes in
|
||||
if ds.tableView == nil {
|
||||
ds.tableView = self.base
|
||||
}
|
||||
ds.tableView?.dataSource = ds
|
||||
ds.applyChanges(items: AnyRealmCollection<E>(results), changes: changes)
|
||||
}
|
||||
}
|
||||
|
||||
public func realmModelSelected<E>(_ modelType: E.Type) -> ControlEvent<E> where E: RealmSwift.Object {
|
||||
|
||||
let source: Observable<E> = self.itemSelected.flatMap { [weak view = self.base as UITableView] indexPath -> Observable<E> in
|
||||
guard let view = view, let ds = view.dataSource as? RxTableViewRealmDataSource<E> else {
|
||||
return Observable.empty()
|
||||
}
|
||||
|
||||
return Observable.just(ds.model(at: indexPath))
|
||||
}
|
||||
|
||||
return ControlEvent(events: source)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension Reactive where Base: UICollectionView {
|
||||
|
||||
public func realmChanges<E>(_ dataSource: RxCollectionViewRealmDataSource<E>)
|
||||
-> RealmBindObserver<E, AnyRealmCollection<E>, RxCollectionViewRealmDataSource<E>> {
|
||||
|
||||
return RealmBindObserver(dataSource: dataSource) {ds, results, changes in
|
||||
if ds.collectionView == nil {
|
||||
ds.collectionView = self.base
|
||||
}
|
||||
ds.collectionView?.dataSource = ds
|
||||
ds.applyChanges(items: AnyRealmCollection<E>(results), changes: changes)
|
||||
}
|
||||
}
|
||||
|
||||
public func realmModelSelected<E>(_ modelType: E.Type) -> ControlEvent<E> where E: RealmSwift.Object {
|
||||
|
||||
let source: Observable<E> = self.itemSelected.flatMap { [weak view = self.base as UICollectionView] indexPath -> Observable<E> in
|
||||
guard let view = view, let ds = view.dataSource as? RxCollectionViewRealmDataSource<E> else {
|
||||
return Observable.empty()
|
||||
}
|
||||
|
||||
return Observable.just(ds.model(at: indexPath))
|
||||
}
|
||||
|
||||
return ControlEvent(events: source)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#elseif os(OSX)
|
||||
// MARK: - macOS / Cocoa
|
||||
|
||||
import Cocoa
|
||||
extension Reactive where Base: NSTableView {
|
||||
|
||||
public func realmChanges<E>(_ dataSource: RxTableViewRealmDataSource<E>)
|
||||
-> RealmBindObserver<E, AnyRealmCollection<E>, RxTableViewRealmDataSource<E>> {
|
||||
|
||||
base.delegate = dataSource
|
||||
base.dataSource = dataSource
|
||||
|
||||
return RealmBindObserver(dataSource: dataSource) {ds, results, changes in
|
||||
if dataSource.tableView == nil {
|
||||
dataSource.tableView = self.base
|
||||
}
|
||||
ds.applyChanges(items: AnyRealmCollection<E>(results), changes: changes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Reactive where Base: NSCollectionView {
|
||||
|
||||
public func realmChanges<E>(_ dataSource: RxCollectionViewRealmDataSource<E>)
|
||||
-> RealmBindObserver<E, AnyRealmCollection<E>, RxCollectionViewRealmDataSource<E>> {
|
||||
|
||||
return RealmBindObserver(dataSource: dataSource) {ds, results, changes in
|
||||
if ds.collectionView == nil {
|
||||
ds.collectionView = self.base
|
||||
}
|
||||
ds.collectionView?.dataSource = ds
|
||||
ds.applyChanges(items: AnyRealmCollection<E>(results), changes: changes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,41 +0,0 @@
|
||||
//
|
||||
// RxRealm extensions
|
||||
//
|
||||
// Copyright (c) 2016 RxSwiftCommunity. All rights reserved.
|
||||
// Check the LICENSE file for details
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
import RealmSwift
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxRealm
|
||||
|
||||
public class RealmBindObserver<O: Object, C: RealmCollection, DS>: ObserverType {
|
||||
typealias BindingType = (DS, C, RealmChangeset?) -> Void
|
||||
public typealias E = (C, RealmChangeset?)
|
||||
|
||||
let dataSource: DS
|
||||
let binding: BindingType
|
||||
|
||||
init(dataSource: DS, binding: @escaping BindingType) {
|
||||
self.dataSource = dataSource
|
||||
self.binding = binding
|
||||
}
|
||||
|
||||
public func on(_ event: Event<E>) {
|
||||
switch event {
|
||||
case .next(let element):
|
||||
binding(dataSource, element.0, element.1)
|
||||
case .error:
|
||||
return
|
||||
case .completed:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func asObserver() -> AnyObserver<E> {
|
||||
return AnyObserver(eventHandler: on)
|
||||
}
|
||||
}
|
||||
@ -1,210 +0,0 @@
|
||||
//
|
||||
// RxRealm extensions
|
||||
//
|
||||
// Copyright (c) 2016 RxSwiftCommunity. All rights reserved.
|
||||
// Check the LICENSE file for details
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
import RealmSwift
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxRealm
|
||||
|
||||
#if os(iOS)
|
||||
// MARK: - iOS / UIKit
|
||||
|
||||
import UIKit
|
||||
|
||||
public typealias CollectionCellFactory<E: Object> = (RxCollectionViewRealmDataSource<E>, UICollectionView, IndexPath, E) -> UICollectionViewCell
|
||||
public typealias CollectionCellConfig<E: Object, CellType: UICollectionViewCell> = (CellType, IndexPath, E) -> Void
|
||||
|
||||
open class RxCollectionViewRealmDataSource <E: Object>: NSObject, UICollectionViewDataSource {
|
||||
private var items: AnyRealmCollection<E>?
|
||||
|
||||
// MARK: - Configuration
|
||||
|
||||
public var collectionView: UICollectionView?
|
||||
public var animated = true
|
||||
|
||||
// MARK: - Init
|
||||
public let cellIdentifier: String
|
||||
public let cellFactory: CollectionCellFactory<E>
|
||||
|
||||
public init(cellIdentifier: String, cellFactory: @escaping CollectionCellFactory<E>) {
|
||||
self.cellIdentifier = cellIdentifier
|
||||
self.cellFactory = cellFactory
|
||||
}
|
||||
|
||||
public init<CellType>(cellIdentifier: String, cellType: CellType.Type, cellConfig: @escaping CollectionCellConfig<E, CellType>) where CellType: UICollectionViewCell {
|
||||
self.cellIdentifier = cellIdentifier
|
||||
self.cellFactory = {ds, cv, ip, model in
|
||||
let cell = cv.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: ip) as! CellType
|
||||
cellConfig(cell, ip, model)
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Data access
|
||||
public func model(at indexPath: IndexPath) -> E {
|
||||
return items![indexPath.row]
|
||||
}
|
||||
|
||||
// MARK: - UICollectionViewDataSource protocol
|
||||
public func numberOfSections(in collectionView: UICollectionView) -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return items?.count ?? 0
|
||||
}
|
||||
|
||||
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||
return cellFactory(self, collectionView, indexPath, items![indexPath.row])
|
||||
}
|
||||
|
||||
// MARK: - Applying changeset to the collection view
|
||||
private let fromRow = {(row: Int) in return IndexPath(row: row, section: 0)}
|
||||
|
||||
func applyChanges(items: AnyRealmCollection<E>, changes: RealmChangeset?) {
|
||||
if self.items == nil {
|
||||
self.items = items
|
||||
}
|
||||
|
||||
guard let collectionView = collectionView else {
|
||||
fatalError("You have to bind a collection view to the data source.")
|
||||
}
|
||||
|
||||
guard animated else {
|
||||
collectionView.reloadData()
|
||||
return
|
||||
}
|
||||
|
||||
guard let changes = changes else {
|
||||
collectionView.reloadData()
|
||||
return
|
||||
}
|
||||
|
||||
let lastItemCount = collectionView.numberOfItems(inSection: 0)
|
||||
guard items.count == lastItemCount + changes.inserted.count - changes.deleted.count else {
|
||||
collectionView.reloadData()
|
||||
return
|
||||
}
|
||||
|
||||
collectionView.performBatchUpdates({[unowned self] in
|
||||
collectionView.deleteItems(at: changes.deleted.map(self.fromRow))
|
||||
collectionView.reloadItems(at: changes.updated.map(self.fromRow))
|
||||
collectionView.insertItems(at: changes.inserted.map(self.fromRow))
|
||||
}, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
#elseif os(OSX)
|
||||
// MARK: - macOS / Cocoa
|
||||
|
||||
import Cocoa
|
||||
|
||||
public typealias CollectionItemFactory<E: Object> = (RxCollectionViewRealmDataSource<E>, NSCollectionView, IndexPath, E) -> NSCollectionViewItem
|
||||
public typealias CollectionItemConfig<E: Object, ItemType: NSCollectionViewItem> = (ItemType, IndexPath, E) -> Void
|
||||
|
||||
open class RxCollectionViewRealmDataSource <E: Object>: NSObject, NSCollectionViewDataSource {
|
||||
|
||||
private var items: AnyRealmCollection<E>?
|
||||
|
||||
// MARK: - Configuration
|
||||
|
||||
public var collectionView: NSCollectionView?
|
||||
public var animated = true
|
||||
|
||||
// MARK: - Init
|
||||
public let itemIdentifier: String
|
||||
public let itemFactory: CollectionItemFactory<E>
|
||||
|
||||
public weak var delegate: NSCollectionViewDelegate?
|
||||
public weak var dataSource: NSCollectionViewDataSource?
|
||||
|
||||
public init(itemIdentifier: String, itemFactory: @escaping CollectionItemFactory<E>) {
|
||||
self.itemIdentifier = itemIdentifier
|
||||
self.itemFactory = itemFactory
|
||||
}
|
||||
|
||||
public init<ItemType>(itemIdentifier: String, itemType: ItemType.Type, itemConfig: @escaping CollectionItemConfig<E, ItemType>) where ItemType: NSCollectionViewItem {
|
||||
self.itemIdentifier = itemIdentifier
|
||||
self.itemFactory = { ds, cv, ip, model in
|
||||
let item = cv.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: itemIdentifier), for: ip) as! ItemType
|
||||
itemConfig(item, ip, model)
|
||||
return item
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - NSCollectionViewDataSource protocol
|
||||
public func numberOfSections(in collectionView: NSCollectionView) -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
public func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return items?.count ?? 0
|
||||
}
|
||||
|
||||
@available(OSX 10.11, *)
|
||||
public func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
|
||||
return itemFactory(self, collectionView, indexPath, items![indexPath.item])
|
||||
}
|
||||
|
||||
// MARK: - Proxy unimplemented data source and delegate methods
|
||||
open override func responds(to aSelector: Selector!) -> Bool {
|
||||
if RxCollectionViewRealmDataSource.instancesRespond(to: aSelector) {
|
||||
return true
|
||||
} else if let delegate = delegate {
|
||||
return delegate.responds(to: aSelector)
|
||||
} else if let dataSource = dataSource {
|
||||
return dataSource.responds(to: aSelector)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
open override func forwardingTarget(for aSelector: Selector!) -> Any? {
|
||||
return delegate ?? dataSource
|
||||
}
|
||||
|
||||
// MARK: - Applying changeset to the collection view
|
||||
private let fromRow = {(row: Int) in return IndexPath(item: row, section: 0)}
|
||||
|
||||
func applyChanges(items: AnyRealmCollection<E>, changes: RealmChangeset?) {
|
||||
if self.items == nil {
|
||||
self.items = items
|
||||
}
|
||||
|
||||
guard let collectionView = collectionView else {
|
||||
fatalError("You have to bind a collection view to the data source.")
|
||||
}
|
||||
|
||||
guard animated else {
|
||||
collectionView.reloadData()
|
||||
return
|
||||
}
|
||||
|
||||
guard let changes = changes else {
|
||||
collectionView.reloadData()
|
||||
return
|
||||
}
|
||||
|
||||
let lastItemCount = collectionView.numberOfItems(inSection: 0)
|
||||
guard items.count == lastItemCount + changes.inserted.count - changes.deleted.count else {
|
||||
collectionView.reloadData()
|
||||
return
|
||||
}
|
||||
|
||||
collectionView.performBatchUpdates({[unowned self] in
|
||||
//TODO: this should be animated, but doesn't seem to be?
|
||||
collectionView.animator().deleteItems(at: Set(changes.deleted.map(self.fromRow)))
|
||||
collectionView.animator().reloadItems(at: Set(changes.updated.map(self.fromRow)))
|
||||
collectionView.animator().insertItems(at: Set(changes.inserted.map(self.fromRow)))
|
||||
}, completionHandler: nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@ -1,223 +0,0 @@
|
||||
//
|
||||
// RxRealm extensions
|
||||
//
|
||||
// Copyright (c) 2016 RxSwiftCommunity. All rights reserved.
|
||||
// Check the LICENSE file for details
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
import RealmSwift
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxRealm
|
||||
|
||||
#if os(iOS)
|
||||
// MARK: - iOS / UIKit
|
||||
|
||||
import UIKit
|
||||
|
||||
public typealias TableCellFactory<E: Object> = (RxTableViewRealmDataSource<E>, UITableView, IndexPath, E) -> UITableViewCell
|
||||
public typealias TableCellConfig<E: Object, CellType: UITableViewCell> = (CellType, IndexPath, E) -> Void
|
||||
|
||||
open class RxTableViewRealmDataSource<E: Object>: NSObject, UITableViewDataSource {
|
||||
|
||||
private var items: AnyRealmCollection<E>?
|
||||
|
||||
// MARK: - Configuration
|
||||
|
||||
public var tableView: UITableView?
|
||||
public var animated = true
|
||||
public var rowAnimations = (
|
||||
insert: UITableView.RowAnimation.automatic,
|
||||
update: UITableView.RowAnimation.automatic,
|
||||
delete: UITableView.RowAnimation.automatic)
|
||||
|
||||
public var headerTitle: String?
|
||||
public var footerTitle: String?
|
||||
|
||||
// MARK: - Init
|
||||
public let cellIdentifier: String
|
||||
public let cellFactory: TableCellFactory<E>
|
||||
|
||||
public init(cellIdentifier: String, cellFactory: @escaping TableCellFactory<E>) {
|
||||
self.cellIdentifier = cellIdentifier
|
||||
self.cellFactory = cellFactory
|
||||
}
|
||||
|
||||
public init<CellType>(cellIdentifier: String, cellType: CellType.Type, cellConfig: @escaping TableCellConfig<E, CellType>) where CellType: UITableViewCell {
|
||||
self.cellIdentifier = cellIdentifier
|
||||
self.cellFactory = {ds, tv, ip, model in
|
||||
let cell = tv.dequeueReusableCell(withIdentifier: cellIdentifier, for: ip) as! CellType
|
||||
cellConfig(cell, ip, model)
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Data access
|
||||
public func model(at indexPath: IndexPath) -> E {
|
||||
return items![indexPath.row]
|
||||
}
|
||||
|
||||
// MARK: - UITableViewDataSource protocol
|
||||
public func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return items?.count ?? 0
|
||||
}
|
||||
|
||||
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
return cellFactory(self, tableView, indexPath, items![indexPath.row])
|
||||
}
|
||||
|
||||
public func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
return headerTitle
|
||||
}
|
||||
|
||||
public func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
|
||||
return footerTitle
|
||||
}
|
||||
|
||||
// MARK: - Applying changeset to the table view
|
||||
private let fromRow = {(row: Int) in return IndexPath(row: row, section: 0)}
|
||||
|
||||
func applyChanges(items: AnyRealmCollection<E>, changes: RealmChangeset?) {
|
||||
if self.items == nil {
|
||||
self.items = items
|
||||
}
|
||||
|
||||
guard let tableView = tableView else {
|
||||
fatalError("You have to bind a table view to the data source.")
|
||||
}
|
||||
|
||||
guard animated else {
|
||||
tableView.reloadData()
|
||||
return
|
||||
}
|
||||
|
||||
guard let changes = changes else {
|
||||
tableView.reloadData()
|
||||
return
|
||||
}
|
||||
|
||||
let lastItemCount = tableView.numberOfRows(inSection: 0)
|
||||
guard items.count == lastItemCount + changes.inserted.count - changes.deleted.count else {
|
||||
tableView.reloadData()
|
||||
return
|
||||
}
|
||||
|
||||
tableView.beginUpdates()
|
||||
tableView.deleteRows(at: changes.deleted.map(fromRow), with: rowAnimations.delete)
|
||||
tableView.insertRows(at: changes.inserted.map(fromRow), with: rowAnimations.insert)
|
||||
tableView.reloadRows(at: changes.updated.map(fromRow), with: rowAnimations.update)
|
||||
tableView.endUpdates()
|
||||
}
|
||||
}
|
||||
|
||||
#elseif os(OSX)
|
||||
// MARK: - macOS / Cocoa
|
||||
|
||||
import Cocoa
|
||||
|
||||
public typealias TableCellFactory<E: Object> = (RxTableViewRealmDataSource<E>, NSTableView, Int, E) -> NSTableCellView
|
||||
public typealias TableCellConfig<E: Object, CellType: NSTableCellView> = (CellType, Int, E) -> Void
|
||||
|
||||
open class RxTableViewRealmDataSource<E: Object>: NSObject, NSTableViewDataSource, NSTableViewDelegate {
|
||||
|
||||
private var items: AnyRealmCollection<E>?
|
||||
|
||||
// MARK: - Configuration
|
||||
|
||||
public var tableView: NSTableView?
|
||||
public var animated = true
|
||||
public var rowAnimations = (
|
||||
insert: NSTableView.AnimationOptions.effectFade,
|
||||
update: NSTableView.AnimationOptions.effectFade,
|
||||
delete: NSTableView.AnimationOptions.effectFade)
|
||||
|
||||
public weak var delegate: NSTableViewDelegate?
|
||||
public weak var dataSource: NSTableViewDataSource?
|
||||
|
||||
// MARK: - Init
|
||||
public let cellIdentifier: String
|
||||
public let cellFactory: TableCellFactory<E>
|
||||
|
||||
public init(cellIdentifier: String, cellFactory: @escaping TableCellFactory<E>) {
|
||||
self.cellIdentifier = cellIdentifier
|
||||
self.cellFactory = cellFactory
|
||||
}
|
||||
|
||||
public init<CellType>(cellIdentifier: String, cellType: CellType.Type, cellConfig: @escaping TableCellConfig<E, CellType>) where CellType: NSTableCellView {
|
||||
self.cellIdentifier = cellIdentifier
|
||||
self.cellFactory = { ds, tv, row, model in
|
||||
let cell = tv.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: cellIdentifier), owner: tv) as! CellType
|
||||
cellConfig(cell, row, model)
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UITableViewDataSource protocol
|
||||
public func numberOfRows(in tableView: NSTableView) -> Int {
|
||||
return items?.count ?? 0
|
||||
}
|
||||
|
||||
public func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
|
||||
return cellFactory(self, tableView, row, items![row])
|
||||
}
|
||||
|
||||
// MARK: - Proxy unimplemented data source and delegate methods
|
||||
open override func responds(to aSelector: Selector!) -> Bool {
|
||||
if RxTableViewRealmDataSource.instancesRespond(to: aSelector) {
|
||||
return true
|
||||
} else if let delegate = delegate {
|
||||
return delegate.responds(to: aSelector)
|
||||
} else if let dataSource = dataSource {
|
||||
return dataSource.responds(to: aSelector)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
open override func forwardingTarget(for aSelector: Selector!) -> Any? {
|
||||
return delegate ?? dataSource
|
||||
}
|
||||
|
||||
// MARK: - Applying changeset to the table view
|
||||
private let fromRow = {(row: Int) in return IndexPath(item: row, section: 0)}
|
||||
|
||||
func applyChanges(items: AnyRealmCollection<E>, changes: RealmChangeset?) {
|
||||
if self.items == nil {
|
||||
self.items = items
|
||||
}
|
||||
|
||||
guard let tableView = tableView else {
|
||||
fatalError("You have to bind a table view to the data source.")
|
||||
}
|
||||
|
||||
guard animated else {
|
||||
tableView.reloadData()
|
||||
return
|
||||
}
|
||||
|
||||
guard let changes = changes else {
|
||||
tableView.reloadData()
|
||||
return
|
||||
}
|
||||
|
||||
let lastItemCount = tableView.numberOfRows
|
||||
guard items.count == lastItemCount + changes.inserted.count - changes.deleted.count else {
|
||||
tableView.reloadData()
|
||||
return
|
||||
}
|
||||
|
||||
tableView.beginUpdates()
|
||||
tableView.removeRows(at: IndexSet(changes.deleted), withAnimation: rowAnimations.delete)
|
||||
tableView.insertRows(at: IndexSet(changes.inserted), withAnimation: rowAnimations.insert)
|
||||
tableView.reloadData(forRowIndexes: IndexSet(changes.updated), columnIndexes: IndexSet([0]))
|
||||
tableView.endUpdates()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||