Replacing IHProgressHUD with PKHUD

This commit is contained in:
Selim Mustafaev 2020-10-11 12:07:01 +03:00
parent c48fa0b041
commit f6bc41fcc6
34 changed files with 91 additions and 2371 deletions

View File

@ -46,10 +46,6 @@
7A3F07AB24360DC800E59687 /* Dated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F07AA24360DC800E59687 /* Dated.swift */; }; 7A3F07AB24360DC800E59687 /* Dated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F07AA24360DC800E59687 /* Dated.swift */; };
7A3F07AD2436350B00E59687 /* SearchController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F07AC2436350B00E59687 /* SearchController.swift */; }; 7A3F07AD2436350B00E59687 /* SearchController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F07AC2436350B00E59687 /* SearchController.swift */; };
7A43F9F8246C8A6200BA5B49 /* JWT.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A43F9F7246C8A6200BA5B49 /* JWT.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 */; }; 7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7924001D3300CBFE6E /* CheckController.swift */; };
7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */; }; 7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */; };
7A530B802401803A00CBFE6E /* Vehicle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7F2401803A00CBFE6E /* Vehicle.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 */; }; 7A64AE742469DFB600ABE48E /* MediaContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE702469DFB600ABE48E /* MediaContentView.swift */; };
7A64AE752469DFB600ABE48E /* MediaBrowserViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE712469DFB600ABE48E /* MediaBrowserViewController.swift */; }; 7A64AE752469DFB600ABE48E /* MediaBrowserViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE712469DFB600ABE48E /* MediaBrowserViewController.swift */; };
7A64AE762469DFB600ABE48E /* ContentTransformers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE722469DFB600ABE48E /* ContentTransformers.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 */; }; 7A659B5924A2B1BA0043A0F2 /* AudioRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A659B5824A2B1BA0043A0F2 /* AudioRecord.swift */; };
7A659B5B24A3768A0043A0F2 /* Substrings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A659B5A24A3768A0043A0F2 /* Substrings.swift */; }; 7A659B5B24A3768A0043A0F2 /* Substrings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A659B5A24A3768A0043A0F2 /* Substrings.swift */; };
7A6DD903242BF4A5009DE740 /* PlateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6DD902242BF4A5009DE740 /* PlateView.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 */; }; 7A96AE31246B2FE400297C33 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A96AE30246B2FE400297C33 /* Constants.swift */; };
7A96AE33246C095700297C33 /* Base64FS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A96AE32246C095700297C33 /* Base64FS.swift */; }; 7A96AE33246C095700297C33 /* Base64FS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A96AE32246C095700297C33 /* Base64FS.swift */; };
7A9FEEC82529AB23001CA50E /* RxRealmDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FEEC72529AB23001CA50E /* RxRealmDataSource.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 */; }; 7AAE6AD324CDDF950023860B /* VehicleEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAE6AD224CDDF950023860B /* VehicleEvent.swift */; };
7AB562BA249C9E9B00473D53 /* Region.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB562B9249C9E9B00473D53 /* Region.swift */; }; 7AB562BA249C9E9B00473D53 /* Region.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB562B9249C9E9B00473D53 /* Region.swift */; };
7AB67E8C2435C38700258F61 /* CustomTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB67E8B2435C38700258F61 /* CustomTextField.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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 7A6DD902242BF4A5009DE740 /* PlateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlateView.swift; sourceTree = "<group>"; };
@ -223,6 +204,7 @@
7A96AE2A246AFD6200297C33 /* Eureka in Frameworks */, 7A96AE2A246AFD6200297C33 /* Eureka in Frameworks */,
7A051611241412CA00FC55AC /* SwiftDate in Frameworks */, 7A051611241412CA00FC55AC /* SwiftDate in Frameworks */,
7A11472323FEA18700B424AF /* RxBlocking in Frameworks */, 7A11472323FEA18700B424AF /* RxBlocking in Frameworks */,
7AABDE1D2532F3EB0041AFC6 /* PKHUD in Frameworks */,
7A530B8B240181F500CBFE6E /* RxRealm in Frameworks */, 7A530B8B240181F500CBFE6E /* RxRealm in Frameworks */,
7A11471F23FEA18700B424AF /* RxRelay in Frameworks */, 7A11471F23FEA18700B424AF /* RxRelay in Frameworks */,
7AF58D2F24029C5200CE01A0 /* MagazineLayout in Frameworks */, 7AF58D2F24029C5200CE01A0 /* MagazineLayout in Frameworks */,
@ -295,8 +277,6 @@
7A11472C23FECA3E00B424AF /* ThirdParty */ = { 7A11472C23FECA3E00B424AF /* ThirdParty */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
7A488C3724A74B990054D0B2 /* RxRealmDataSources */,
7A64AE772469E16100ABE48E /* IHProgressHUD */,
7A64AE6E2469DFB600ABE48E /* ATGMediaBrowser */, 7A64AE6E2469DFB600ABE48E /* ATGMediaBrowser */,
7A6DD90724329144009DE740 /* CenterTextLayer.swift */, 7A6DD90724329144009DE740 /* CenterTextLayer.swift */,
7A96AE32246C095700297C33 /* Base64FS.swift */, 7A96AE32246C095700297C33 /* Base64FS.swift */,
@ -366,17 +346,6 @@
path = Extensions; path = Extensions;
sourceTree = "<group>"; 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 */ = { 7A530B7C24017FBE00CBFE6E /* Cells */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -404,19 +373,6 @@
path = ATGMediaBrowser; path = ATGMediaBrowser;
sourceTree = "<group>"; 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 */ = { 7A6DD901242BF48D009DE740 /* Views */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -484,6 +440,7 @@
7A0516172414EC1200FC55AC /* RxDataSources */, 7A0516172414EC1200FC55AC /* RxDataSources */,
7A96AE29246AFD6200297C33 /* Eureka */, 7A96AE29246AFD6200297C33 /* Eureka */,
7A813DC02508C4D900CC93B9 /* ExceptionCatcher */, 7A813DC02508C4D900CC93B9 /* ExceptionCatcher */,
7AABDE1C2532F3EB0041AFC6 /* PKHUD */,
); );
productName = AutoCat; productName = AutoCat;
productReference = 7A1146FD23FDE7E500B424AF /* AutoCat.app */; productReference = 7A1146FD23FDE7E500B424AF /* AutoCat.app */;
@ -523,6 +480,7 @@
7A0516142414EC1200FC55AC /* XCRemoteSwiftPackageReference "RxDataSources" */, 7A0516142414EC1200FC55AC /* XCRemoteSwiftPackageReference "RxDataSources" */,
7A96AE28246AFD6200297C33 /* XCRemoteSwiftPackageReference "Eureka" */, 7A96AE28246AFD6200297C33 /* XCRemoteSwiftPackageReference "Eureka" */,
7A813DBF2508C4D900CC93B9 /* XCRemoteSwiftPackageReference "ExceptionCatcher" */, 7A813DBF2508C4D900CC93B9 /* XCRemoteSwiftPackageReference "ExceptionCatcher" */,
7AABDE1B2532F3EB0041AFC6 /* XCRemoteSwiftPackageReference "PKHUD" */,
); );
productRefGroup = 7A1146FE23FDE7E500B424AF /* Products */; productRefGroup = 7A1146FE23FDE7E500B424AF /* Products */;
projectDirPath = ""; projectDirPath = "";
@ -542,10 +500,8 @@
7A7547DE2403180A004E8406 /* SectionHeader.xib in Resources */, 7A7547DE2403180A004E8406 /* SectionHeader.xib in Resources */,
7A11470D23FDE7E600B424AF /* LaunchScreen.storyboard in Resources */, 7A11470D23FDE7E600B424AF /* LaunchScreen.storyboard in Resources */,
7A6DD90A24329541009DE740 /* RoadNumbers2.0.otf in Resources */, 7A6DD90A24329541009DE740 /* RoadNumbers2.0.otf in Resources */,
7A64AE802469E16100ABE48E /* .gitkeep in Resources */,
7A11470A23FDE7E600B424AF /* Assets.xcassets in Resources */, 7A11470A23FDE7E600B424AF /* Assets.xcassets in Resources */,
7A11470823FDE7E500B424AF /* Main.storyboard in Resources */, 7A11470823FDE7E500B424AF /* Main.storyboard in Resources */,
7A64AE832469E16100ABE48E /* IHProgressHUD.bundle in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -560,7 +516,6 @@
7A96AE33246C095700297C33 /* Base64FS.swift in Sources */, 7A96AE33246C095700297C33 /* Base64FS.swift in Sources */,
7A530B802401803A00CBFE6E /* Vehicle.swift in Sources */, 7A530B802401803A00CBFE6E /* Vehicle.swift in Sources */,
7A96AE31246B2FE400297C33 /* Constants.swift in Sources */, 7A96AE31246B2FE400297C33 /* Constants.swift in Sources */,
7A64AE822469E16100ABE48E /* IHProgressHUD.swift in Sources */,
7A11470123FDE7E500B424AF /* AppDelegate.swift in Sources */, 7A11470123FDE7E500B424AF /* AppDelegate.swift in Sources */,
7ADF6C9D250FA96000F237B2 /* SwiftMaskTextfield.swift in Sources */, 7ADF6C9D250FA96000F237B2 /* SwiftMaskTextfield.swift in Sources */,
7A27ADF924A09CAD0035F39E /* CocoaError.swift in Sources */, 7A27ADF924A09CAD0035F39E /* CocoaError.swift in Sources */,
@ -570,7 +525,6 @@
7A3F07AD2436350B00E59687 /* SearchController.swift in Sources */, 7A3F07AD2436350B00E59687 /* SearchController.swift in Sources */,
7AB562BA249C9E9B00473D53 /* Region.swift in Sources */, 7AB562BA249C9E9B00473D53 /* Region.swift in Sources */,
7A659B5924A2B1BA0043A0F2 /* AudioRecord.swift in Sources */, 7A659B5924A2B1BA0043A0F2 /* AudioRecord.swift in Sources */,
7A488C3C24A74B990054D0B2 /* RxTableViewRealmDataSource.swift in Sources */,
7A6DD90C24335A6D009DE740 /* FlagLayer.swift in Sources */, 7A6DD90C24335A6D009DE740 /* FlagLayer.swift in Sources */,
7AE26A3524F31B0700625033 /* EventsController.swift in Sources */, 7AE26A3524F31B0700625033 /* EventsController.swift in Sources */,
7AB67E8C2435C38700258F61 /* CustomTextField.swift in Sources */, 7AB67E8C2435C38700258F61 /* CustomTextField.swift in Sources */,
@ -590,8 +544,6 @@
7A11474923FF2B2D00B424AF /* Response.swift in Sources */, 7A11474923FF2B2D00B424AF /* Response.swift in Sources */,
7A64AE762469DFB600ABE48E /* ContentTransformers.swift in Sources */, 7A64AE762469DFB600ABE48E /* ContentTransformers.swift in Sources */,
7A11471823FDEBFA00B424AF /* ReportController.swift in Sources */, 7A11471823FDEBFA00B424AF /* ReportController.swift in Sources */,
7A64AE7E2469E16100ABE48E /* RadialGradientLayer.swift in Sources */,
7A64AE7F2469E16100ABE48E /* IndefiniteAnimatedView.swift in Sources */,
7AE24C5F251F1B4E00758E39 /* Buttons.swift in Sources */, 7AE24C5F251F1B4E00758E39 /* Buttons.swift in Sources */,
7A11471A23FE839000B424AF /* AuthController.swift in Sources */, 7A11471A23FE839000B424AF /* AuthController.swift in Sources */,
7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */, 7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */,
@ -610,18 +562,15 @@
7A43F9F8246C8A6200BA5B49 /* JWT.swift in Sources */, 7A43F9F8246C8A6200BA5B49 /* JWT.swift in Sources */,
7A6DD903242BF4A5009DE740 /* PlateView.swift in Sources */, 7A6DD903242BF4A5009DE740 /* PlateView.swift in Sources */,
7ADF6C9F251201D200F237B2 /* GlobalEventsController.swift in Sources */, 7ADF6C9F251201D200F237B2 /* GlobalEventsController.swift in Sources */,
7A488C3F24A74B990054D0B2 /* RealmBindObserver.swift in Sources */,
7AAE6AD324CDDF950023860B /* VehicleEvent.swift in Sources */, 7AAE6AD324CDDF950023860B /* VehicleEvent.swift in Sources */,
7A11470323FDE7E500B424AF /* SceneDelegate.swift in Sources */, 7A11470323FDE7E500B424AF /* SceneDelegate.swift in Sources */,
7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */, 7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */,
7A813DCB250B5DC900CC93B9 /* LocationPickerController.swift in Sources */, 7A813DCB250B5DC900CC93B9 /* LocationPickerController.swift in Sources */,
7A11474423FF06CA00B424AF /* Api.swift in Sources */, 7A11474423FF06CA00B424AF /* Api.swift in Sources */,
7A488C3D24A74B990054D0B2 /* RxCollectionViewRealmDataSource.swift in Sources */,
7A9FEEC82529AB23001CA50E /* RxRealmDataSource.swift in Sources */, 7A9FEEC82529AB23001CA50E /* RxRealmDataSource.swift in Sources */,
7AB67E8E2435D1A000258F61 /* CustomButton.swift in Sources */, 7AB67E8E2435D1A000258F61 /* CustomButton.swift in Sources */,
7A21112A24FC3D7E003BBF6F /* AudioEngine.swift in Sources */, 7A21112A24FC3D7E003BBF6F /* AudioEngine.swift in Sources */,
7A8A220B248D67B60073DFD9 /* VehicleReportImage.swift in Sources */, 7A8A220B248D67B60073DFD9 /* VehicleReportImage.swift in Sources */,
7A488C3E24A74B990054D0B2 /* Reactive+RxRealmDataSources.swift in Sources */,
7ADF6C95250D037700F237B2 /* ShowEventController.swift in Sources */, 7ADF6C95250D037700F237B2 /* ShowEventController.swift in Sources */,
7A27ADC7249D43210035F39E /* RegionsController.swift in Sources */, 7A27ADC7249D43210035F39E /* RegionsController.swift in Sources */,
7A05161A2414FF0900FC55AC /* DateSection.swift in Sources */, 7A05161A2414FF0900FC55AC /* DateSection.swift in Sources */,
@ -630,7 +579,6 @@
7ADF6C93250B954900F237B2 /* Navigation.swift in Sources */, 7ADF6C93250B954900F237B2 /* Navigation.swift in Sources */,
7A64AE752469DFB600ABE48E /* MediaBrowserViewController.swift in Sources */, 7A64AE752469DFB600ABE48E /* MediaBrowserViewController.swift in Sources */,
7A64AE732469DFB600ABE48E /* DismissAnimationController.swift in Sources */, 7A64AE732469DFB600ABE48E /* DismissAnimationController.swift in Sources */,
7A64AE812469E16100ABE48E /* ProgressAnimatedView.swift in Sources */,
7ADF6C97250F41B000F237B2 /* PNKeyboard.swift in Sources */, 7ADF6C97250F41B000F237B2 /* PNKeyboard.swift in Sources */,
7A000AA224C2EEDE001F5B00 /* Location.swift in Sources */, 7A000AA224C2EEDE001F5B00 /* Location.swift in Sources */,
7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */, 7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */,
@ -897,6 +845,14 @@
minimumVersion = 5.2.1; 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" */ = { 7AF58D2D24029C5200CE01A0 /* XCRemoteSwiftPackageReference "MagazineLayout" */ = {
isa = XCRemoteSwiftPackageReference; isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/airbnb/MagazineLayout"; repositoryURL = "https://github.com/airbnb/MagazineLayout";
@ -976,6 +932,11 @@
package = 7A96AE28246AFD6200297C33 /* XCRemoteSwiftPackageReference "Eureka" */; package = 7A96AE28246AFD6200297C33 /* XCRemoteSwiftPackageReference "Eureka" */;
productName = Eureka; productName = Eureka;
}; };
7AABDE1C2532F3EB0041AFC6 /* PKHUD */ = {
isa = XCSwiftPackageProductDependency;
package = 7AABDE1B2532F3EB0041AFC6 /* XCRemoteSwiftPackageReference "PKHUD" */;
productName = PKHUD;
};
7AF58D2E24029C5200CE01A0 /* MagazineLayout */ = { 7AF58D2E24029C5200CE01A0 /* MagazineLayout */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
package = 7AF58D2D24029C5200CE01A0 /* XCRemoteSwiftPackageReference "MagazineLayout" */; package = 7AF58D2D24029C5200CE01A0 /* XCRemoteSwiftPackageReference "MagazineLayout" */;

View File

@ -37,6 +37,15 @@
"version": "1.6.3" "version": "1.6.3"
} }
}, },
{
"package": "PKHUD",
"repositoryURL": "https://github.com/pkluz/PKHUD.git",
"state": {
"branch": null,
"revision": "8fd26f23057c6bebd6695524b1c3e05e93aba571",
"version": "5.4.0"
}
},
{ {
"package": "Realm", "package": "Realm",
"repositoryURL": "https://github.com/realm/realm-cocoa", "repositoryURL": "https://github.com/realm/realm-cocoa",

View File

@ -3,6 +3,7 @@ import RealmSwift
import RxSwift import RxSwift
import RxCocoa import RxCocoa
import os.log import os.log
import PKHUD
extension OSLog { extension OSLog {
static let startup = OSLog(subsystem: "pro.aliencat.autocat.startup", category: "startup") static let startup = OSLog(subsystem: "pro.aliencat.autocat.startup", category: "startup")
@ -68,8 +69,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
Realm.Configuration.defaultConfiguration = config Realm.Configuration.defaultConfiguration = config
IHProgressHUD.set(defaultStyle: .dark) HUD.dimsBackground = true
IHProgressHUD.set(defaultMaskType: .black) HUD.allowsInteraction = false
Logging.URLRequests = { _ in false }; Logging.URLRequests = { _ in false };

View File

@ -1,5 +1,6 @@
import UIKit import UIKit
import RxSwift import RxSwift
import PKHUD
class AudioRecordCell: UITableViewCell, ConfigurableCell { class AudioRecordCell: UITableViewCell, ConfigurableCell {
@ -74,7 +75,7 @@ class AudioRecordCell: UITableViewCell, ConfigurableCell {
try AudioPlayer.shared.play(url: url) try AudioPlayer.shared.play(url: url)
} catch { } catch {
print("Error playing audio record: \(error.localizedDescription)") print("Error playing audio record: \(error.localizedDescription)")
IHProgressHUD.showError(withStatus: error.localizedDescription) HUD.show(error: error)
} }
} }
} }

View File

@ -3,6 +3,7 @@ import RxSwift
import RxCocoa import RxCocoa
import RealmSwift import RealmSwift
import AuthenticationServices import AuthenticationServices
import PKHUD
class AuthController: UIViewController, ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding { class AuthController: UIViewController, ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding {
@ -35,20 +36,20 @@ class AuthController: UIViewController, ASAuthorizationControllerDelegate, ASAut
@IBAction func loginTapped(_ sender: UIButton) { @IBAction func loginTapped(_ sender: UIButton) {
guard let email = self.username.text, let pass = self.password.text else { return } guard let email = self.username.text, let pass = self.password.text else { return }
IHProgressHUD.show() HUD.show(.progress)
Api.login(email: email, password: pass) Api.login(email: email, password: pass)
.observeOn(MainScheduler.instance) .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) .disposed(by: self.bag)
} }
@IBAction func signupTapped(_ sender: UIButton) { @IBAction func signupTapped(_ sender: UIButton) {
guard let email = self.username.text, let pass = self.password.text else { return } guard let email = self.username.text, let pass = self.password.text else { return }
IHProgressHUD.show() HUD.show(.progress)
Api.signUp(email: email, password: pass) Api.signUp(email: email, password: pass)
.observeOn(MainScheduler.instance) .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) .disposed(by: self.bag)
} }
@ -64,29 +65,24 @@ class AuthController: UIViewController, ASAuthorizationControllerDelegate, ASAut
} }
func goToMainScreen(user: User) { func goToMainScreen(user: User) {
// guard let realm = try? Realm() else { guard let realm = try? Realm() else {
// IHProgressHUD.showError(withStatus: "Database error") HUD.flash(.labeledError(title: nil, subtitle: "Database error"))
// return return
// } }
IHProgressHUD.dismiss() HUD.hide()
// if user.email != Settings.shared.user.email { if user.email != Settings.shared.user.email {
// try? realm.write { try? realm.write {
// realm.deleteAll() realm.deleteAll()
// } }
// } }
Settings.shared.user = user Settings.shared.user = user
let storyboard = UIStoryboard(name: "Main", bundle: nil) let storyboard = UIStoryboard(name: "Main", bundle: nil)
self.view.window?.rootViewController = storyboard.instantiateViewController(identifier: "MainSplitController") self.view.window?.rootViewController = storyboard.instantiateViewController(identifier: "MainSplitController")
} }
func displayError(error: Error) {
IHProgressHUD.showError(withStatus: error.localizedDescription)
print(error)
}
// MARK: - Apple SignIn // MARK: - Apple SignIn
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor { func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
@ -97,14 +93,14 @@ class AuthController: UIViewController, ASAuthorizationControllerDelegate, ASAut
switch authorization.credential { switch authorization.credential {
case let appleIDCredential as ASAuthorizationAppleIDCredential: case let appleIDCredential as ASAuthorizationAppleIDCredential:
guard let email = appleIDCredential.email else { guard let email = appleIDCredential.email else {
IHProgressHUD.showError(withStatus: "Cannot get email") HUD.flash(.labeledError(title: nil, subtitle: "Cannot get email"))
return return
} }
IHProgressHUD.show() HUD.show(.progress)
Api.signIn(email: email, password: appleIDCredential.user) Api.signIn(email: email, password: appleIDCredential.user)
.observeOn(MainScheduler.instance) .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) .disposed(by: self.bag)
if let tokenData = appleIDCredential.identityToken { if let tokenData = appleIDCredential.identityToken {
@ -116,7 +112,7 @@ class AuthController: UIViewController, ASAuthorizationControllerDelegate, ASAut
}) })
} }
default: default:
IHProgressHUD.showError(withStatus: "Unsupported authorization credential") HUD.flash(.labeledError(title: nil, subtitle: "Unsupported authorization credential"))
break break
} }
} }

View File

@ -3,6 +3,7 @@ import RealmSwift
import RxSwift import RxSwift
import SwiftDate import SwiftDate
import RxRealm import RxRealm
import PKHUD
enum EventAction { enum EventAction {
case doNotSend case doNotSend
@ -99,12 +100,12 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat
self.number.text = nil self.number.text = nil
self.check.isEnabled = false self.check.isEnabled = false
IHProgressHUD.show() HUD.show(.progress)
self.check(number: numberNormalized, action: .receiveAndSend).subscribe { vehicle in self.check(number: numberNormalized, action: .receiveAndSend).subscribe { vehicle in
self.updateDetailController(with: vehicle) self.updateDetailController(with: vehicle)
IHProgressHUD.dismiss() HUD.hide()
} onError: { error in } onError: { error in
IHProgressHUD.show(error: error) HUD.show(error: error)
} }
.disposed(by: self.bag) .disposed(by: self.bag)
@ -198,7 +199,7 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat
// MARK: - Contextual actions // MARK: - Contextual actions
func update(vehicle: Vehicle) { func update(vehicle: Vehicle) {
IHProgressHUD.show() HUD.show(.progress)
var eventAction: EventAction = .doNotSend var eventAction: EventAction = .doNotSend
if vehicle.unrecognized, let savedEvent = vehicle.events.first { 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.check(number: vehicle.getNumber(), action: eventAction, force: true).subscribe { vehicle in
self.updateDetailController(with: vehicle) self.updateDetailController(with: vehicle)
IHProgressHUD.dismiss() HUD.hide()
} onError: { error in } onError: { error in
IHProgressHUD.show(error: error) HUD.show(error: error)
} }
.disposed(by: self.bag) .disposed(by: self.bag)
} }

View File

@ -2,6 +2,7 @@ import UIKit
import WebKit import WebKit
import CommonCrypto import CommonCrypto
import RxSwift import RxSwift
import PKHUD
struct TokenResponse: Codable { struct TokenResponse: Codable {
var id_token: String var id_token: String
@ -58,7 +59,7 @@ class GoogleSignInController: UIViewController, WKNavigationDelegate {
.subscribe(onSuccess: { _ in .subscribe(onSuccess: { _ in
self.dismiss(animated: true, completion: self.completion) self.dismiss(animated: true, completion: self.completion)
}, onError: { error in }, onError: { error in
IHProgressHUD.showError(withStatus: error.localizedDescription) HUD.flash(.labeledError(title: nil, subtitle: error.localizedDescription))
}) })
.disposed(by: self.bag) .disposed(by: self.bag)
return return

View File

@ -3,6 +3,7 @@ import MapKit
import RxSwift import RxSwift
import Realm import Realm
import RealmSwift import RealmSwift
import PKHUD
class EventPin: NSObject, MKAnnotation { class EventPin: NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D var coordinate: CLLocationCoordinate2D
@ -148,18 +149,18 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
func deleteEvent(index: Int, completion: @escaping (Bool) -> Void) { func deleteEvent(index: Int, completion: @escaping (Bool) -> Void) {
guard let vehicle = self.vehicle else { guard let vehicle = self.vehicle else {
IHProgressHUD.showError(withStatus: "Unknown vehicle") HUD.flash(.labeledError(title: nil, subtitle: "Unknown vehicle"))
return return
} }
let event = vehicle.events[index] let event = vehicle.events[index]
if let eventId = event.id { if let eventId = event.id {
IHProgressHUD.show() HUD.show(.progress)
Api.remove(event: eventId).observeOn(MainScheduler.instance).subscribe(onSuccess: { vehicle in Api.remove(event: eventId).observeOn(MainScheduler.instance).subscribe(onSuccess: { vehicle in
completion(self.update(vehicle: vehicle)) completion(self.update(vehicle: vehicle))
}, onError: { error in }, onError: { error in
completion(false) completion(false)
IHProgressHUD.show(error: error) HUD.show(error: error)
print(error) print(error)
}).disposed(by: self.bag) }).disposed(by: self.bag)
} else { } else {
@ -169,7 +170,7 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
func editEvent(index: Int) { func editEvent(index: Int) {
guard let vehicle = self.vehicle else { guard let vehicle = self.vehicle else {
IHProgressHUD.showError(withStatus: "Unknown vehicle") HUD.flash(.labeledError(title: nil, subtitle: "Unknown vehicle"))
return return
} }
@ -182,12 +183,12 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
controller.onDone = { newEvent in controller.onDone = { newEvent in
newEvent.id = event.id newEvent.id = event.id
self.navigationController?.popViewController(animated: true, completion: { self.navigationController?.popViewController(animated: true, completion: {
IHProgressHUD.show() HUD.show(.progress)
Api.edit(event: newEvent) Api.edit(event: newEvent)
.observeOn(MainScheduler.instance) .observeOn(MainScheduler.instance)
.subscribe(onSuccess: { self.update(vehicle: $0) }, onError: .subscribe(onSuccess: { self.update(vehicle: $0) }, onError:
{ error in { error in
IHProgressHUD.show(error: error) HUD.show(error: error)
}) })
.disposed(by: self.bag) .disposed(by: self.bag)
}) })
@ -197,7 +198,7 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
@objc func addEvent(_ sender: UIBarButtonItem) { @objc func addEvent(_ sender: UIBarButtonItem) {
guard let vehicle = self.vehicle else { guard let vehicle = self.vehicle else {
IHProgressHUD.showError(withStatus: "Unknown vehicle") HUD.flash(.labeledError(title: nil, subtitle: "Unknown vehicle"))
return return
} }
@ -206,12 +207,12 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
controller.title = "Add new event" controller.title = "Add new event"
controller.onDone = { newEvent in controller.onDone = { newEvent in
self.navigationController?.popViewController(animated: true, completion: { self.navigationController?.popViewController(animated: true, completion: {
IHProgressHUD.show() HUD.show(.progress)
Api.add(event: newEvent, to: vehicle.getNumber()) Api.add(event: newEvent, to: vehicle.getNumber())
.observeOn(MainScheduler.instance) .observeOn(MainScheduler.instance)
.subscribe(onSuccess: { self.update(vehicle: $0) }, onError: .subscribe(onSuccess: { self.update(vehicle: $0) }, onError:
{ error in { error in
IHProgressHUD.show(error: error) HUD.show(error: error)
}) })
.disposed(by: self.bag) .disposed(by: self.bag)
}) })
@ -231,10 +232,10 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
self.vehicle?.events.append(objectsIn: vehicle.events) self.vehicle?.events.append(objectsIn: vehicle.events)
} }
self.updateInterface() self.updateInterface()
IHProgressHUD.dismiss() HUD.hide()
return true return true
} catch { } catch {
IHProgressHUD.show(error: error) HUD.show(error: error)
print(error) print(error)
return false return false
} }

View File

@ -1,6 +1,7 @@
import UIKit import UIKit
import MapKit import MapKit
import RxSwift import RxSwift
import PKHUD
class GlobalEventsController: UIViewController { class GlobalEventsController: UIViewController {
@ -16,7 +17,7 @@ class GlobalEventsController: UIViewController {
self.map.showsZoomControls = true self.map.showsZoomControls = true
#endif #endif
IHProgressHUD.show() HUD.show(.progress)
Api.events(with: self.filter) Api.events(with: self.filter)
.observeOn(MainScheduler.init()) .observeOn(MainScheduler.init())
.subscribe(onSuccess: { events in .subscribe(onSuccess: { events in
@ -25,9 +26,9 @@ class GlobalEventsController: UIViewController {
self.map.removeAnnotations(self.map.annotations) self.map.removeAnnotations(self.map.annotations)
self.map.addAnnotations(pins) self.map.addAnnotations(pins)
self.map.centerOnPins() self.map.centerOnPins()
IHProgressHUD.dismiss() HUD.hide()
}) { error in }) { error in
IHProgressHUD.show(error: error) HUD.show(error: error)
} }
.disposed(by: self.bag) .disposed(by: self.bag)
} }

View File

@ -7,6 +7,7 @@ import Intents
import CoreSpotlight import CoreSpotlight
import MobileCoreServices import MobileCoreServices
import os.log import os.log
import PKHUD
class RecordsController: UIViewController, UITableViewDelegate { class RecordsController: UIViewController, UITableViewDelegate {
@ -84,7 +85,7 @@ class RecordsController: UIViewController, UITableViewDelegate {
@objc func onAddVoiceRecord(_ sender: UIBarButtonItem) { @objc func onAddVoiceRecord(_ sender: UIBarButtonItem) {
guard let recorder = self.recorder else { 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 return
} }
@ -142,10 +143,10 @@ class RecordsController: UIViewController, UITableViewDelegate {
}) { error in }) { error in
if let alert = alert { if let alert = alert {
alert.dismiss(animated: true) { alert.dismiss(animated: true) {
IHProgressHUD.show(error: error) HUD.show(error: error)
} }
} else { } else {
IHProgressHUD.show(error: error) HUD.show(error: error)
} }
self.addButton.isEnabled = true self.addButton.isEnabled = true
} }
@ -274,7 +275,7 @@ class RecordsController: UIViewController, UITableViewDelegate {
self.present(controller, animated: true) self.present(controller, animated: true)
} catch { } catch {
print("Error sharing audio record: \(error.localizedDescription)") 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 let showText = UIAlertAction(title: "Show recognized text", style: .default) { action in

View File

@ -3,6 +3,7 @@ import RxDataSources
import RxSwift import RxSwift
import RxCocoa import RxCocoa
import RealmSwift import RealmSwift
import PKHUD
class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDelegate { class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDelegate {
@ -160,9 +161,9 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
} }
func update(vehicle: Vehicle, at indexPath: IndexPath) { 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 Api.checkVehicle(by: vehicle.getNumber(), force: true).observeOn(MainScheduler.instance).subscribe { newVehicle in
IHProgressHUD.dismiss() HUD.hide()
if let realm = try? Realm() { if let realm = try? Realm() {
if realm.object(ofType: Vehicle.self, forPrimaryKey: vehicle.getNumber()) != nil { if realm.object(ofType: Vehicle.self, forPrimaryKey: vehicle.getNumber()) != nil {
try? realm.write { try? realm.write {
@ -173,7 +174,7 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
self.datasource[indexPath] = newVehicle self.datasource[indexPath] = newVehicle
self.updateDetailController(with: newVehicle) self.updateDetailController(with: newVehicle)
} onError: { err in } onError: { err in
IHProgressHUD.show(error: err) HUD.show(error: err)
}.disposed(by: self.bag) }.disposed(by: self.bag)
} }
} }

View File

@ -1,4 +1,5 @@
import UIKit import UIKit
import PKHUD
extension NSError { extension NSError {
var displayMessage: (title: String, body: String) { var displayMessage: (title: String, body: String) {
@ -50,9 +51,9 @@ extension UIViewController {
} }
} }
extension IHProgressHUD { extension HUD {
static func show(error: Error) { static func show(error: Error) {
let msg = (error as NSError).displayMessage 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)
} }
} }

View File

@ -2,6 +2,7 @@ import UIKit
import os.log import os.log
import AVFoundation import AVFoundation
import RxSwift import RxSwift
import PKHUD
class SceneDelegate: UIResponder, UIWindowSceneDelegate { class SceneDelegate: UIResponder, UIWindowSceneDelegate {
@ -145,7 +146,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func openReport(with number: String) { func openReport(with number: String) {
guard let rootController = self.window?.rootViewController else { return } guard let rootController = self.window?.rootViewController else { return }
IHProgressHUD.show() HUD.show(.progress)
_ = Api.getReport(for: number).observeOn(MainScheduler.instance).subscribe { vehicle in _ = Api.getReport(for: number).observeOn(MainScheduler.instance).subscribe { vehicle in
let sb = UIStoryboard(name: "Main", bundle: nil) let sb = UIStoryboard(name: "Main", bundle: nil)
let controller = sb.instantiateViewController(identifier: "ReportController") as ReportController let controller = sb.instantiateViewController(identifier: "ReportController") as ReportController
@ -154,9 +155,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
nav.modalPresentationStyle = .fullScreen nav.modalPresentationStyle = .fullScreen
controller.navigationItem.leftBarButtonItem = BlockBarButtonItem(barButtonSystemItem: .close) { _ in nav.dismiss(animated: true) } controller.navigationItem.leftBarButtonItem = BlockBarButtonItem(barButtonSystemItem: .close) { _ in nav.dismiss(animated: true) }
rootController.present(nav, animated: true) rootController.present(nav, animated: true)
IHProgressHUD.dismiss() HUD.hide()
} onError: { error in } onError: { error in
IHProgressHUD.show(error: error) HUD.show(error: error)
} }
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 873 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 752 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 662 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 912 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

File diff suppressed because it is too large Load Diff

View File

@ -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))
}
}

View File

@ -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!
}
}

View File

@ -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)
}
}
}

View File

@ -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

View File

@ -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)
}
}

View File

@ -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

View File

@ -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