ارفع راسك فوق انته سوري حر ... :green_heart::green_heart:

Skip to content
Snippets Groups Projects
Commit 4a47fd0c authored by George's avatar George
Browse files

networkManager Files

parent 664e6bdf
Branches
No related tags found
No related merge requests found
Showing
with 1779 additions and 3 deletions
......@@ -7,6 +7,63 @@
objects = {
/* Begin PBXBuildFile section */
5326833C2AE9175900A364C0 /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5326833A2AE9175900A364C0 /* LoginViewController.swift */; };
5326833D2AE9175900A364C0 /* LoginViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5326833B2AE9175900A364C0 /* LoginViewController.xib */; };
532683512AE91A6F00A364C0 /* Montserrat-ExtraLightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 5326833F2AE91A6E00A364C0 /* Montserrat-ExtraLightItalic.ttf */; };
532683522AE91A6F00A364C0 /* Montserrat-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 532683402AE91A6E00A364C0 /* Montserrat-Light.ttf */; };
532683532AE91A6F00A364C0 /* Montserrat-ExtraBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 532683412AE91A6E00A364C0 /* Montserrat-ExtraBold.ttf */; };
532683542AE91A6F00A364C0 /* Montserrat-LightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 532683422AE91A6E00A364C0 /* Montserrat-LightItalic.ttf */; };
532683552AE91A6F00A364C0 /* Montserrat-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 532683432AE91A6E00A364C0 /* Montserrat-Italic.ttf */; };
532683562AE91A6F00A364C0 /* Montserrat-MediumItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 532683442AE91A6E00A364C0 /* Montserrat-MediumItalic.ttf */; };
532683572AE91A6F00A364C0 /* Montserrat-BoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 532683452AE91A6E00A364C0 /* Montserrat-BoldItalic.ttf */; };
532683582AE91A6F00A364C0 /* Montserrat-SemiBoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 532683462AE91A6F00A364C0 /* Montserrat-SemiBoldItalic.ttf */; };
532683592AE91A6F00A364C0 /* Montserrat-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 532683472AE91A6F00A364C0 /* Montserrat-SemiBold.ttf */; };
5326835A2AE91A6F00A364C0 /* Montserrat-Thin.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 532683482AE91A6F00A364C0 /* Montserrat-Thin.ttf */; };
5326835B2AE91A6F00A364C0 /* Montserrat-BlackItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 532683492AE91A6F00A364C0 /* Montserrat-BlackItalic.ttf */; };
5326835C2AE91A6F00A364C0 /* Montserrat-ThinItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 5326834A2AE91A6F00A364C0 /* Montserrat-ThinItalic.ttf */; };
5326835D2AE91A6F00A364C0 /* Montserrat-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 5326834B2AE91A6F00A364C0 /* Montserrat-Bold.ttf */; };
5326835E2AE91A6F00A364C0 /* Montserrat-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 5326834C2AE91A6F00A364C0 /* Montserrat-Regular.ttf */; };
5326835F2AE91A6F00A364C0 /* Montserrat-Black.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 5326834D2AE91A6F00A364C0 /* Montserrat-Black.ttf */; };
532683602AE91A6F00A364C0 /* Montserrat-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 5326834E2AE91A6F00A364C0 /* Montserrat-Medium.ttf */; };
532683612AE91A6F00A364C0 /* Montserrat-ExtraLight.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 5326834F2AE91A6F00A364C0 /* Montserrat-ExtraLight.ttf */; };
532683622AE91A6F00A364C0 /* Montserrat-ExtraBoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 532683502AE91A6F00A364C0 /* Montserrat-ExtraBoldItalic.ttf */; };
532683652AE91D0800A364C0 /* UIFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683642AE91D0800A364C0 /* UIFont.swift */; };
532683742AE923A500A364C0 /* KNTextFieldView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 532683672AE923A500A364C0 /* KNTextFieldView.xib */; };
532683752AE923A500A364C0 /* KNTextFieldView+Protocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683682AE923A500A364C0 /* KNTextFieldView+Protocols.swift */; };
532683762AE923A500A364C0 /* KNTextFieldViewHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683692AE923A500A364C0 /* KNTextFieldViewHelper.swift */; };
532683772AE923A500A364C0 /* KNTextFieldView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5326836A2AE923A500A364C0 /* KNTextFieldView.swift */; };
532683782AE923A500A364C0 /* FieldTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5326836C2AE923A500A364C0 /* FieldTableViewCell.xib */; };
532683792AE923A500A364C0 /* FieldTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5326836D2AE923A500A364C0 /* FieldTableViewCell.swift */; };
5326837A2AE923A500A364C0 /* KNFieldDropDownAddressObjectProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5326836F2AE923A500A364C0 /* KNFieldDropDownAddressObjectProtocol.swift */; };
5326837B2AE923A500A364C0 /* KNFieldType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683702AE923A500A364C0 /* KNFieldType.swift */; };
5326837C2AE923A500A364C0 /* KNField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683712AE923A500A364C0 /* KNField.swift */; };
5326837D2AE923A500A364C0 /* KNFieldBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683722AE923A500A364C0 /* KNFieldBuilder.swift */; };
5326837E2AE923A500A364C0 /* KNFieldDropdownObjectProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683732AE923A500A364C0 /* KNFieldDropdownObjectProtocol.swift */; };
532683812AE923DE00A364C0 /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 532683802AE923DE00A364C0 /* Alamofire */; };
532683832AE928F900A364C0 /* KNTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683822AE928F900A364C0 /* KNTableViewCell.swift */; };
532683852AE9293200A364C0 /* KNComponentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683842AE9293200A364C0 /* KNComponentView.swift */; };
532683872AE9295500A364C0 /* Nameable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683862AE9295500A364C0 /* Nameable.swift */; };
532683892AE92B6800A364C0 /* Observable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683882AE92B6800A364C0 /* Observable.swift */; };
5326838B2AE92CA500A364C0 /* JSONField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5326838A2AE92CA500A364C0 /* JSONField.swift */; };
5326838D2AE92D9900A364C0 /* CGFLoat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5326838C2AE92D9900A364C0 /* CGFLoat.swift */; };
532683962AE9482300A364C0 /* Network+Endpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5326838F2AE9482200A364C0 /* Network+Endpoint.swift */; };
532683972AE9482300A364C0 /* Network+Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683902AE9482200A364C0 /* Network+Result.swift */; };
532683992AE9482300A364C0 /* Network+Rechability.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683922AE9482300A364C0 /* Network+Rechability.swift */; };
5326839A2AE9482300A364C0 /* Network+Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683932AE9482300A364C0 /* Network+Types.swift */; };
5326839B2AE9482300A364C0 /* NetworkRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683942AE9482300A364C0 /* NetworkRequest.swift */; };
5326839C2AE9482300A364C0 /* Network+Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683952AE9482300A364C0 /* Network+Error.swift */; };
5326839F2AE9489C00A364C0 /* Reachability in Frameworks */ = {isa = PBXBuildFile; productRef = 5326839E2AE9489C00A364C0 /* Reachability */; };
532683A12AE948FF00A364C0 /* AppManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683A02AE948FF00A364C0 /* AppManager.swift */; };
532683A32AE9497100A364C0 /* Keys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683A22AE9497100A364C0 /* Keys.swift */; };
532683A52AE94A3500A364C0 /* KNTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683A42AE94A3500A364C0 /* KNTextField.swift */; };
532683A72AE94ADC00A364C0 /* KNObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683A62AE94ADC00A364C0 /* KNObject.swift */; };
532683A92AE94B1300A364C0 /* UIInt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683A82AE94B1300A364C0 /* UIInt.swift */; };
532683AB2AE94BA500A364C0 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683AA2AE94BA500A364C0 /* UIView.swift */; };
532683AD2AE94BFC00A364C0 /* Logs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683AC2AE94BFC00A364C0 /* Logs.swift */; };
532683AF2AE94C2F00A364C0 /* NSLayoutConstraints.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683AE2AE94C2F00A364C0 /* NSLayoutConstraints.swift */; };
532683B12AE94C9400A364C0 /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683B02AE94C9400A364C0 /* Dictionary.swift */; };
532683B32AE98D0000A364C0 /* UILabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683B22AE98D0000A364C0 /* UILabel.swift */; };
532683B52AE98FB600A364C0 /* UIString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683B42AE98FB600A364C0 /* UIString.swift */; };
5E394EBE28A9CC7600396F33 /* BatteryStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E394EBD28A9CC7600396F33 /* BatteryStatus.swift */; };
5E716A271F63A0B100A2DBC3 /* DistanceCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E716A261F63A0B100A2DBC3 /* DistanceCalculator.swift */; };
5E716A291F63A45A00A2DBC3 /* RequestManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E716A281F63A45A00A2DBC3 /* RequestManager.swift */; };
......@@ -65,6 +122,61 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
5326833A2AE9175900A364C0 /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = "<group>"; };
5326833B2AE9175900A364C0 /* LoginViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LoginViewController.xib; sourceTree = "<group>"; };
5326833F2AE91A6E00A364C0 /* Montserrat-ExtraLightItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-ExtraLightItalic.ttf"; sourceTree = "<group>"; };
532683402AE91A6E00A364C0 /* Montserrat-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-Light.ttf"; sourceTree = "<group>"; };
532683412AE91A6E00A364C0 /* Montserrat-ExtraBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-ExtraBold.ttf"; sourceTree = "<group>"; };
532683422AE91A6E00A364C0 /* Montserrat-LightItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-LightItalic.ttf"; sourceTree = "<group>"; };
532683432AE91A6E00A364C0 /* Montserrat-Italic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-Italic.ttf"; sourceTree = "<group>"; };
532683442AE91A6E00A364C0 /* Montserrat-MediumItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-MediumItalic.ttf"; sourceTree = "<group>"; };
532683452AE91A6E00A364C0 /* Montserrat-BoldItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-BoldItalic.ttf"; sourceTree = "<group>"; };
532683462AE91A6F00A364C0 /* Montserrat-SemiBoldItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-SemiBoldItalic.ttf"; sourceTree = "<group>"; };
532683472AE91A6F00A364C0 /* Montserrat-SemiBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-SemiBold.ttf"; sourceTree = "<group>"; };
532683482AE91A6F00A364C0 /* Montserrat-Thin.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-Thin.ttf"; sourceTree = "<group>"; };
532683492AE91A6F00A364C0 /* Montserrat-BlackItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-BlackItalic.ttf"; sourceTree = "<group>"; };
5326834A2AE91A6F00A364C0 /* Montserrat-ThinItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-ThinItalic.ttf"; sourceTree = "<group>"; };
5326834B2AE91A6F00A364C0 /* Montserrat-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-Bold.ttf"; sourceTree = "<group>"; };
5326834C2AE91A6F00A364C0 /* Montserrat-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-Regular.ttf"; sourceTree = "<group>"; };
5326834D2AE91A6F00A364C0 /* Montserrat-Black.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-Black.ttf"; sourceTree = "<group>"; };
5326834E2AE91A6F00A364C0 /* Montserrat-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-Medium.ttf"; sourceTree = "<group>"; };
5326834F2AE91A6F00A364C0 /* Montserrat-ExtraLight.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-ExtraLight.ttf"; sourceTree = "<group>"; };
532683502AE91A6F00A364C0 /* Montserrat-ExtraBoldItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Montserrat-ExtraBoldItalic.ttf"; sourceTree = "<group>"; };
532683642AE91D0800A364C0 /* UIFont.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIFont.swift; sourceTree = "<group>"; };
532683672AE923A500A364C0 /* KNTextFieldView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = KNTextFieldView.xib; sourceTree = "<group>"; };
532683682AE923A500A364C0 /* KNTextFieldView+Protocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "KNTextFieldView+Protocols.swift"; sourceTree = "<group>"; };
532683692AE923A500A364C0 /* KNTextFieldViewHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KNTextFieldViewHelper.swift; sourceTree = "<group>"; };
5326836A2AE923A500A364C0 /* KNTextFieldView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KNTextFieldView.swift; sourceTree = "<group>"; };
5326836C2AE923A500A364C0 /* FieldTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FieldTableViewCell.xib; sourceTree = "<group>"; };
5326836D2AE923A500A364C0 /* FieldTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FieldTableViewCell.swift; sourceTree = "<group>"; };
5326836F2AE923A500A364C0 /* KNFieldDropDownAddressObjectProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KNFieldDropDownAddressObjectProtocol.swift; sourceTree = "<group>"; };
532683702AE923A500A364C0 /* KNFieldType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KNFieldType.swift; sourceTree = "<group>"; };
532683712AE923A500A364C0 /* KNField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KNField.swift; sourceTree = "<group>"; };
532683722AE923A500A364C0 /* KNFieldBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KNFieldBuilder.swift; sourceTree = "<group>"; };
532683732AE923A500A364C0 /* KNFieldDropdownObjectProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KNFieldDropdownObjectProtocol.swift; sourceTree = "<group>"; };
532683822AE928F900A364C0 /* KNTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KNTableViewCell.swift; sourceTree = "<group>"; };
532683842AE9293200A364C0 /* KNComponentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KNComponentView.swift; sourceTree = "<group>"; };
532683862AE9295500A364C0 /* Nameable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Nameable.swift; sourceTree = "<group>"; };
532683882AE92B6800A364C0 /* Observable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Observable.swift; sourceTree = "<group>"; };
5326838A2AE92CA500A364C0 /* JSONField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONField.swift; sourceTree = "<group>"; };
5326838C2AE92D9900A364C0 /* CGFLoat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGFLoat.swift; sourceTree = "<group>"; };
5326838F2AE9482200A364C0 /* Network+Endpoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Network+Endpoint.swift"; sourceTree = "<group>"; };
532683902AE9482200A364C0 /* Network+Result.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Network+Result.swift"; sourceTree = "<group>"; };
532683922AE9482300A364C0 /* Network+Rechability.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Network+Rechability.swift"; sourceTree = "<group>"; };
532683932AE9482300A364C0 /* Network+Types.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Network+Types.swift"; sourceTree = "<group>"; };
532683942AE9482300A364C0 /* NetworkRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkRequest.swift; sourceTree = "<group>"; };
532683952AE9482300A364C0 /* Network+Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Network+Error.swift"; sourceTree = "<group>"; };
532683A02AE948FF00A364C0 /* AppManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppManager.swift; sourceTree = "<group>"; };
532683A22AE9497100A364C0 /* Keys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keys.swift; sourceTree = "<group>"; };
532683A42AE94A3500A364C0 /* KNTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KNTextField.swift; sourceTree = "<group>"; };
532683A62AE94ADC00A364C0 /* KNObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KNObject.swift; sourceTree = "<group>"; };
532683A82AE94B1300A364C0 /* UIInt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIInt.swift; sourceTree = "<group>"; };
532683AA2AE94BA500A364C0 /* UIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIView.swift; sourceTree = "<group>"; };
532683AC2AE94BFC00A364C0 /* Logs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logs.swift; sourceTree = "<group>"; };
532683AE2AE94C2F00A364C0 /* NSLayoutConstraints.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSLayoutConstraints.swift; sourceTree = "<group>"; };
532683B02AE94C9400A364C0 /* Dictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = "<group>"; };
532683B22AE98D0000A364C0 /* UILabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UILabel.swift; sourceTree = "<group>"; };
532683B42AE98FB600A364C0 /* UIString.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIString.swift; sourceTree = "<group>"; };
5E394EBD28A9CC7600396F33 /* BatteryStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatteryStatus.swift; sourceTree = "<group>"; };
5E716A261F63A0B100A2DBC3 /* DistanceCalculator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DistanceCalculator.swift; sourceTree = "<group>"; };
5E716A281F63A45A00A2DBC3 /* RequestManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestManager.swift; sourceTree = "<group>"; };
......@@ -132,10 +244,12 @@
buildActionMask = 2147483647;
files = (
CBDEEB8A1B8EB6A4006BC126 /* SystemConfiguration.framework in Frameworks */,
5326839F2AE9489C00A364C0 /* Reachability in Frameworks */,
CBCE82EF1B8D253600A7318B /* CoreData.framework in Frameworks */,
5EE3CA342998948F002C86E4 /* FirebaseAnalytics in Frameworks */,
CEDB048717ED50C1000E7EDF /* CoreLocation.framework in Frameworks */,
CED4879917DB1DF4007FCF57 /* MessageUI.framework in Frameworks */,
532683812AE923DE00A364C0 /* Alamofire in Frameworks */,
CED4871C17DB1BF6007FCF57 /* UIKit.framework in Frameworks */,
5EE3CA362998948F002C86E4 /* FirebaseCrashlytics in Frameworks */,
5EE3CA39299894B9002C86E4 /* InAppSettingsKit in Frameworks */,
......@@ -154,6 +268,114 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
532683392AE9174700A364C0 /* Views */ = {
isa = PBXGroup;
children = (
532683822AE928F900A364C0 /* KNTableViewCell.swift */,
532683662AE923A500A364C0 /* BMTextFieldView */,
5326833A2AE9175900A364C0 /* LoginViewController.swift */,
5326833B2AE9175900A364C0 /* LoginViewController.xib */,
532683842AE9293200A364C0 /* KNComponentView.swift */,
);
name = Views;
sourceTree = "<group>";
};
5326833E2AE91A6200A364C0 /* Fonts */ = {
isa = PBXGroup;
children = (
5326834D2AE91A6F00A364C0 /* Montserrat-Black.ttf */,
532683492AE91A6F00A364C0 /* Montserrat-BlackItalic.ttf */,
5326834B2AE91A6F00A364C0 /* Montserrat-Bold.ttf */,
532683452AE91A6E00A364C0 /* Montserrat-BoldItalic.ttf */,
532683412AE91A6E00A364C0 /* Montserrat-ExtraBold.ttf */,
532683502AE91A6F00A364C0 /* Montserrat-ExtraBoldItalic.ttf */,
5326834F2AE91A6F00A364C0 /* Montserrat-ExtraLight.ttf */,
5326833F2AE91A6E00A364C0 /* Montserrat-ExtraLightItalic.ttf */,
532683432AE91A6E00A364C0 /* Montserrat-Italic.ttf */,
532683402AE91A6E00A364C0 /* Montserrat-Light.ttf */,
532683422AE91A6E00A364C0 /* Montserrat-LightItalic.ttf */,
5326834E2AE91A6F00A364C0 /* Montserrat-Medium.ttf */,
532683442AE91A6E00A364C0 /* Montserrat-MediumItalic.ttf */,
5326834C2AE91A6F00A364C0 /* Montserrat-Regular.ttf */,
532683472AE91A6F00A364C0 /* Montserrat-SemiBold.ttf */,
532683462AE91A6F00A364C0 /* Montserrat-SemiBoldItalic.ttf */,
532683482AE91A6F00A364C0 /* Montserrat-Thin.ttf */,
5326834A2AE91A6F00A364C0 /* Montserrat-ThinItalic.ttf */,
);
name = Fonts;
sourceTree = "<group>";
};
532683632AE91CAC00A364C0 /* helpers */ = {
isa = PBXGroup;
children = (
5326838E2AE947D900A364C0 /* Network */,
532683642AE91D0800A364C0 /* UIFont.swift */,
5326838C2AE92D9900A364C0 /* CGFLoat.swift */,
532683862AE9295500A364C0 /* Nameable.swift */,
532683A02AE948FF00A364C0 /* AppManager.swift */,
532683A22AE9497100A364C0 /* Keys.swift */,
532683A42AE94A3500A364C0 /* KNTextField.swift */,
532683A62AE94ADC00A364C0 /* KNObject.swift */,
532683A82AE94B1300A364C0 /* UIInt.swift */,
532683AA2AE94BA500A364C0 /* UIView.swift */,
532683AC2AE94BFC00A364C0 /* Logs.swift */,
532683AE2AE94C2F00A364C0 /* NSLayoutConstraints.swift */,
532683B02AE94C9400A364C0 /* Dictionary.swift */,
532683B22AE98D0000A364C0 /* UILabel.swift */,
);
name = helpers;
sourceTree = "<group>";
};
532683662AE923A500A364C0 /* BMTextFieldView */ = {
isa = PBXGroup;
children = (
532683672AE923A500A364C0 /* KNTextFieldView.xib */,
532683682AE923A500A364C0 /* KNTextFieldView+Protocols.swift */,
532683692AE923A500A364C0 /* KNTextFieldViewHelper.swift */,
5326836A2AE923A500A364C0 /* KNTextFieldView.swift */,
5326836B2AE923A500A364C0 /* Cell */,
5326836E2AE923A500A364C0 /* Model */,
);
path = BMTextFieldView;
sourceTree = "<group>";
};
5326836B2AE923A500A364C0 /* Cell */ = {
isa = PBXGroup;
children = (
5326836C2AE923A500A364C0 /* FieldTableViewCell.xib */,
5326836D2AE923A500A364C0 /* FieldTableViewCell.swift */,
);
path = Cell;
sourceTree = "<group>";
};
5326836E2AE923A500A364C0 /* Model */ = {
isa = PBXGroup;
children = (
5326836F2AE923A500A364C0 /* KNFieldDropDownAddressObjectProtocol.swift */,
532683702AE923A500A364C0 /* KNFieldType.swift */,
532683712AE923A500A364C0 /* KNField.swift */,
532683722AE923A500A364C0 /* KNFieldBuilder.swift */,
532683732AE923A500A364C0 /* KNFieldDropdownObjectProtocol.swift */,
);
path = Model;
sourceTree = "<group>";
};
5326838E2AE947D900A364C0 /* Network */ = {
isa = PBXGroup;
children = (
532683882AE92B6800A364C0 /* Observable.swift */,
5326838F2AE9482200A364C0 /* Network+Endpoint.swift */,
532683952AE9482300A364C0 /* Network+Error.swift */,
532683922AE9482300A364C0 /* Network+Rechability.swift */,
532683902AE9482200A364C0 /* Network+Result.swift */,
532683932AE9482300A364C0 /* Network+Types.swift */,
532683942AE9482300A364C0 /* NetworkRequest.swift */,
5326838A2AE92CA500A364C0 /* JSONField.swift */,
532683B42AE98FB600A364C0 /* UIString.swift */,
);
name = Network;
sourceTree = "<group>";
};
CED4870F17DB1BF6007FCF57 = {
isa = PBXGroup;
children = (
......@@ -190,10 +412,12 @@
CED4872117DB1BF6007FCF57 /* TraccarClient */ = {
isa = PBXGroup;
children = (
532683632AE91CAC00A364C0 /* helpers */,
CE5899C71B115C9100ED70D2 /* Images.xcassets */,
CED4873317DB1BF6007FCF57 /* MainStoryboard.storyboard */,
CEF643241B919FFA00195CEA /* LaunchScreen.xib */,
CEF643371B91A94600195CEA /* Localizable.strings */,
532683392AE9174700A364C0 /* Views */,
CED4872217DB1BF6007FCF57 /* Supporting Files */,
CB7ED0831F662BAF00A33FCF /* AppDelegate.swift */,
CB4197921F674A3E008F301C /* DatabaseHelper.swift */,
......@@ -214,6 +438,7 @@
CED4872217DB1BF6007FCF57 /* Supporting Files */ = {
isa = PBXGroup;
children = (
5326833E2AE91A6200A364C0 /* Fonts */,
CED4872317DB1BF6007FCF57 /* TraccarClient-Info.plist */,
CED4872917DB1BF6007FCF57 /* TraccarClient-Prefix.pch */,
CBCE82F01B8D265800A7318B /* TraccarClient.xcdatamodeld */,
......@@ -264,6 +489,8 @@
5EE3CA332998948F002C86E4 /* FirebaseAnalytics */,
5EE3CA352998948F002C86E4 /* FirebaseCrashlytics */,
5EE3CA38299894B9002C86E4 /* InAppSettingsKit */,
532683802AE923DE00A364C0 /* Alamofire */,
5326839E2AE9489C00A364C0 /* Reachability */,
);
productName = TraccarClient;
productReference = CED4871817DB1BF6007FCF57 /* TraccarClient.app */;
......@@ -330,6 +557,8 @@
packageReferences = (
5EE3CA322998948F002C86E4 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
5EE3CA37299894B9002C86E4 /* XCRemoteSwiftPackageReference "InAppSettingsKit" */,
5326837F2AE923DE00A364C0 /* XCRemoteSwiftPackageReference "Alamofire" */,
5326839D2AE9489C00A364C0 /* XCRemoteSwiftPackageReference "Reachability" */,
);
productRefGroup = CED4871917DB1BF6007FCF57 /* Products */;
projectDirPath = "";
......@@ -346,11 +575,32 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
532683582AE91A6F00A364C0 /* Montserrat-SemiBoldItalic.ttf in Resources */,
532683572AE91A6F00A364C0 /* Montserrat-BoldItalic.ttf in Resources */,
CEF6433C1B91AA9400195CEA /* MainStoryboard.storyboard in Resources */,
5326835B2AE91A6F00A364C0 /* Montserrat-BlackItalic.ttf in Resources */,
CEF6433D1B91AA9400195CEA /* Localizable.strings in Resources */,
532683552AE91A6F00A364C0 /* Montserrat-Italic.ttf in Resources */,
5326833D2AE9175900A364C0 /* LoginViewController.xib in Resources */,
CE5899C81B115C9100ED70D2 /* Images.xcassets in Resources */,
5326835F2AE91A6F00A364C0 /* Montserrat-Black.ttf in Resources */,
532683742AE923A500A364C0 /* KNTextFieldView.xib in Resources */,
532683622AE91A6F00A364C0 /* Montserrat-ExtraBoldItalic.ttf in Resources */,
5326835E2AE91A6F00A364C0 /* Montserrat-Regular.ttf in Resources */,
532683522AE91A6F00A364C0 /* Montserrat-Light.ttf in Resources */,
CEF643271B919FFA00195CEA /* LaunchScreen.xib in Resources */,
532683592AE91A6F00A364C0 /* Montserrat-SemiBold.ttf in Resources */,
CED4879B17DB1E61007FCF57 /* InAppSettings.bundle in Resources */,
532683532AE91A6F00A364C0 /* Montserrat-ExtraBold.ttf in Resources */,
532683612AE91A6F00A364C0 /* Montserrat-ExtraLight.ttf in Resources */,
532683782AE923A500A364C0 /* FieldTableViewCell.xib in Resources */,
5326835D2AE91A6F00A364C0 /* Montserrat-Bold.ttf in Resources */,
532683542AE91A6F00A364C0 /* Montserrat-LightItalic.ttf in Resources */,
5326835C2AE91A6F00A364C0 /* Montserrat-ThinItalic.ttf in Resources */,
532683562AE91A6F00A364C0 /* Montserrat-MediumItalic.ttf in Resources */,
5326835A2AE91A6F00A364C0 /* Montserrat-Thin.ttf in Resources */,
532683602AE91A6F00A364C0 /* Montserrat-Medium.ttf in Resources */,
532683512AE91A6F00A364C0 /* Montserrat-ExtraLightItalic.ttf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -386,18 +636,52 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5326833C2AE9175900A364C0 /* LoginViewController.swift in Sources */,
532683962AE9482300A364C0 /* Network+Endpoint.swift in Sources */,
CB7ED0801F6602CD00A33FCF /* Position.swift in Sources */,
532683972AE9482300A364C0 /* Network+Result.swift in Sources */,
5326837A2AE923A500A364C0 /* KNFieldDropDownAddressObjectProtocol.swift in Sources */,
CBAA0F7F1F68E807008BBBBE /* MainViewController.swift in Sources */,
532683B52AE98FB600A364C0 /* UIString.swift in Sources */,
5326839C2AE9482300A364C0 /* Network+Error.swift in Sources */,
532683AF2AE94C2F00A364C0 /* NSLayoutConstraints.swift in Sources */,
CB7ED0821F661B4F00A33FCF /* PositionProvider.swift in Sources */,
532683832AE928F900A364C0 /* KNTableViewCell.swift in Sources */,
5326837C2AE923A500A364C0 /* KNField.swift in Sources */,
532683AB2AE94BA500A364C0 /* UIView.swift in Sources */,
5326839A2AE9482300A364C0 /* Network+Types.swift in Sources */,
CB4197991F67724F008F301C /* NetworkManager.swift in Sources */,
532683B32AE98D0000A364C0 /* UILabel.swift in Sources */,
5326838D2AE92D9900A364C0 /* CGFLoat.swift in Sources */,
CB7ED0841F662BAF00A33FCF /* AppDelegate.swift in Sources */,
532683AD2AE94BFC00A364C0 /* Logs.swift in Sources */,
5E394EBE28A9CC7600396F33 /* BatteryStatus.swift in Sources */,
532683872AE9295500A364C0 /* Nameable.swift in Sources */,
5326837E2AE923A500A364C0 /* KNFieldDropdownObjectProtocol.swift in Sources */,
532683752AE923A500A364C0 /* KNTextFieldView+Protocols.swift in Sources */,
532683A52AE94A3500A364C0 /* KNTextField.swift in Sources */,
5E716A2B1F63A60800A2DBC3 /* ProtocolFormatter.swift in Sources */,
532683772AE923A500A364C0 /* KNTextFieldView.swift in Sources */,
532683652AE91D0800A364C0 /* UIFont.swift in Sources */,
CBCE82F21B8D265800A7318B /* TraccarClient.xcdatamodeld in Sources */,
532683762AE923A500A364C0 /* KNTextFieldViewHelper.swift in Sources */,
CBAA0F7D1F68E14C008BBBBE /* StatusViewController.swift in Sources */,
532683A72AE94ADC00A364C0 /* KNObject.swift in Sources */,
532683A12AE948FF00A364C0 /* AppManager.swift in Sources */,
532683A32AE9497100A364C0 /* Keys.swift in Sources */,
532683A92AE94B1300A364C0 /* UIInt.swift in Sources */,
5326837D2AE923A500A364C0 /* KNFieldBuilder.swift in Sources */,
532683852AE9293200A364C0 /* KNComponentView.swift in Sources */,
CBAA0F811F68EB62008BBBBE /* TrackingController.swift in Sources */,
532683992AE9482300A364C0 /* Network+Rechability.swift in Sources */,
5E716A271F63A0B100A2DBC3 /* DistanceCalculator.swift in Sources */,
532683792AE923A500A364C0 /* FieldTableViewCell.swift in Sources */,
5326838B2AE92CA500A364C0 /* JSONField.swift in Sources */,
532683892AE92B6800A364C0 /* Observable.swift in Sources */,
5326837B2AE923A500A364C0 /* KNFieldType.swift in Sources */,
532683B12AE94C9400A364C0 /* Dictionary.swift in Sources */,
5E716A291F63A45A00A2DBC3 /* RequestManager.swift in Sources */,
5326839B2AE9482300A364C0 /* NetworkRequest.swift in Sources */,
CB4197931F674A3E008F301C /* DatabaseHelper.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
......@@ -867,6 +1151,22 @@
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
5326837F2AE923DE00A364C0 /* XCRemoteSwiftPackageReference "Alamofire" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/Alamofire/Alamofire";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 5.8.0;
};
};
5326839D2AE9489C00A364C0 /* XCRemoteSwiftPackageReference "Reachability" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/ashleymills/Reachability.swift";
requirement = {
branch = master;
kind = branch;
};
};
5EE3CA322998948F002C86E4 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
......@@ -886,6 +1186,16 @@
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
532683802AE923DE00A364C0 /* Alamofire */ = {
isa = XCSwiftPackageProductDependency;
package = 5326837F2AE923DE00A364C0 /* XCRemoteSwiftPackageReference "Alamofire" */;
productName = Alamofire;
};
5326839E2AE9489C00A364C0 /* Reachability */ = {
isa = XCSwiftPackageProductDependency;
package = 5326839D2AE9489C00A364C0 /* XCRemoteSwiftPackageReference "Reachability" */;
productName = Reachability;
};
5EE3CA332998948F002C86E4 /* FirebaseAnalytics */ = {
isa = XCSwiftPackageProductDependency;
package = 5EE3CA322998948F002C86E4 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
......
......@@ -9,6 +9,15 @@
"version" : "0.20220203.2"
}
},
{
"identity" : "alamofire",
"kind" : "remoteSourceControl",
"location" : "https://github.com/Alamofire/Alamofire",
"state" : {
"revision" : "b2fa556e4e48cbf06cf8c63def138c98f4b811fa",
"version" : "5.8.0"
}
},
{
"identity" : "boringssl-swiftpm",
"kind" : "remoteSourceControl",
......@@ -108,6 +117,15 @@
"version" : "2.3.1"
}
},
{
"identity" : "reachability.swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/ashleymills/Reachability.swift",
"state" : {
"branch" : "master",
"revision" : "a81b7367f2c46875f29577e03a60c39cdfad0c8d"
}
},
{
"identity" : "swift-protobuf",
"kind" : "remoteSourceControl",
......
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
uuid = "C69DA6DD-5592-40A4-92DB-D8BF97EDB011"
type = "1"
version = "2.0">
</Bucket>
//
// AppManager.swift
// TraccarClient
//
// Created by George Makhoul on 25/10/2023.
// Copyright © 2023 Traccar. All rights reserved.
//
import Foundation
import UIKit
let app = AppManager.si
enum KNEnvironment {
case sandbox
case development
case production
}
final class AppManager {
// MARK: - Init
static let si = AppManager()
private init() {
//
}
// MARK: - Logs
var logsAreEnabled: Bool {
environment == .production ? true : true
}
// MARK: - Request
var useShortLogsForRequests = false //true
var logRequest: [Endpoint] = [
.all,
.signin,
.signup,
.companySignup,
.signupPassword,
.companySignupPassword,
.signupVerifyCode,
.addresses,
.bankAccount,
.contactus,
.upload_Media,
.product_builder_step_information_media,
.documents,
.favorite,
.product_builder_step_shipping,
.variant,
.salesOrders,
.salesOrderDetails,
.checkout_shipping_methods,
.sales_summary,
.checkout_payment_methods,
.checkout_add_coupon,
.checkout_remove_coupon
]
// MARK: - Data
var environment: KNEnvironment = .sandbox
var delegate: AppDelegate!
var isUpdatingProfile: Bool = false
var isLoggedIn: Bool {
if let _ = UserDefaults.standard.string(forKey: Keys.User.access_token) {
return true
} else if let _ = UserDefaults.standard.string(forKey: Keys.guestToken) {
return true
}
return false
}
// func saveToUserDefaults(model: UserModel) {
// let ud = UserDefaults.standard
//
// ud.set(model.id, forKey: Keys.User.id)
// ud.set(model.user_type, forKey: Keys.User.user_type)
// ud.set(model.access_token, forKey: Keys.User.access_token)
// ud.set(model.refresh_token, forKey: Keys.User.refresh_token)
// ud.set(model.picture, forKey: Keys.User.picture)
// ud.set(model.full_name, forKey: Keys.User.fullName)
// ud.set(model.phone, forKey: Keys.User.phone)
// ud.set(model.prefix, forKey: Keys.User.prefix)
// ud.set(model.is_document_completed, forKey: Keys.User.is_document_completed)
// ud.set(model.is_bank_completed, forKey: Keys.User.is_bank_completed)
// ud.set(model.is_warehouse_added, forKey: Keys.User.is_warehouse_added)
// ud.set(model.is_account_type_pending, forKey: Keys.User.is_account_type_pending)
// ud.set(model.account_type, forKey: Keys.User.account_type)
// }
}
//
// FieldTableViewCell.swift
// traccar
//
// Created by iOS Developer on 2/6/22.
//
import UIKit
final class FieldTableViewCell: KNTableViewCell {
// MARK: - Outlets
@IBOutlet var fieldView: KNTextFieldView!
@IBOutlet private weak var fieldViewLeadingConstraint: NSLayoutConstraint!
@IBOutlet private weak var fieldViewTrailingConstraint: NSLayoutConstraint!
// MARK: - Properties
private var indexPath: IndexPath?
private var field: KNField?
var isLeadingSpaceZero: Bool = false
weak var delegate: KNTextFieldViewDelegate?
weak var dropdownDelegate: KNTextFieldViewDropdownDelegate?
weak var prefixDelegate: KNTextFieldViewPrefixDelegate?
// MARK: - Lifecycle
override func awakeFromNib() {
super.awakeFromNib()
setupUI()
}
// MARK: - Setup
func set(field: KNField?, indexPath: IndexPath?) {
self.indexPath = indexPath
self.field = field
fieldView.textField.textAlignment = .left
updateUI()
}
func set(field: KNField?, indexPath: IndexPath?, isLeadingSpaceZero: Bool) {
self.isLeadingSpaceZero = isLeadingSpaceZero
self.set(field: field, indexPath: indexPath)
fieldView.textField.textAlignment = .left
if let field = field {
fieldView.textField.textAlignment = .left
fieldView.semanticContentAttribute = .forceLeftToRight
}
}
// MARK: - UI
private func setupUI() {
contentView.backgroundColor = .white
}
private func updateUI() {
guard let field = field else { return }
fieldView.setupUI()
fieldView.prefixDelegate = prefixDelegate
fieldView.delegate = delegate
fieldView.dropdownDelegate = dropdownDelegate
fieldView.set(field: field)
fieldView.textField.textAlignment = .left
fieldView.semanticContentAttribute = .forceLeftToRight
fieldViewLeadingConstraint.constant = isLeadingSpaceZero ? 0 : 16
fieldViewTrailingConstraint.constant = isLeadingSpaceZero ? 0 : 16
}
}
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="FieldTableViewCell" rowHeight="475" id="KGk-i7-Jjw" customClass="FieldTableViewCell" customModule="opa" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="280" height="475"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
<rect key="frame" x="0.0" y="0.0" width="280" height="475"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ja2-lQ-BKV" customClass="KNTextFieldView" customModule="opa" customModuleProvider="target">
<rect key="frame" x="16" y="0.0" width="248" height="450"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="Ja2-lQ-BKV" secondAttribute="trailing" constant="16" id="Niq-du-wkN"/>
<constraint firstAttribute="bottom" secondItem="Ja2-lQ-BKV" secondAttribute="bottom" constant="25" id="hpt-Fg-Vp8"/>
<constraint firstItem="Ja2-lQ-BKV" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="jBI-Ud-W3x"/>
<constraint firstItem="Ja2-lQ-BKV" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="16" id="ufc-ZF-ttC"/>
</constraints>
</tableViewCellContentView>
<viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
<connections>
<outlet property="fieldView" destination="Ja2-lQ-BKV" id="Mem-Kd-4xD"/>
<outlet property="fieldViewLeadingConstraint" destination="ufc-ZF-ttC" id="50H-ox-Tj7"/>
<outlet property="fieldViewTrailingConstraint" destination="Niq-du-wkN" id="fQX-t4-YbC"/>
</connections>
<point key="canvasLocation" x="155.07246376811597" y="57.254464285714285"/>
</tableViewCell>
</objects>
</document>
//
// KNTextFieldView+Protocols.swift
// traccar
//
// Created by iOS Developer on 2/9/22.
//
import Foundation
import UIKit
protocol KNTextFieldViewDelegate: AnyObject {
func updateUI(for field: KNField?)
}
protocol KNTextFieldViewDropdownDelegate: AnyObject {
func dropdownTapped(with field: KNField?)
}
protocol KNTextFieldViewPrefixDelegate: AnyObject {
func prefixTapped(with field: KNField?)
}
//
// KNTextFieldView.swift
// traccar
//
import UIKit
final class KNTextFieldView: KNComponentView {
// MARK: - Outlets
@IBOutlet private weak var view: UIView!
@IBOutlet private weak var boxView: UIView!
// top
@IBOutlet private weak var topView: UIView!
@IBOutlet private weak var titleLabel: UILabel!
@IBOutlet private weak var titleLabel_bottom: NSLayoutConstraint!
@IBOutlet private weak var countLabel: UILabel!
@IBOutlet private weak var countLabel_leading: NSLayoutConstraint!
@IBOutlet private weak var countLabel_width: NSLayoutConstraint!
// field
@IBOutlet private weak var fieldView: UIView!
@IBOutlet private weak var borderView: UIView!
@IBOutlet private weak var prefixView: UIView!
@IBOutlet private weak var prefixView_width: NSLayoutConstraint!
@IBOutlet private weak var prefixFlagIcon: UIImageView!
@IBOutlet private weak var prefixFlagIcon_leading: NSLayoutConstraint!
@IBOutlet private weak var prefixFlagIcon_width: NSLayoutConstraint! //31
@IBOutlet private weak var prefixFlagIcon_height: NSLayoutConstraint! //20
@IBOutlet private weak var prefixLabel_leading: NSLayoutConstraint! //2
@IBOutlet private weak var prefixLabel: UILabel!
@IBOutlet private weak var prefixLabel_trailing: NSLayoutConstraint! //2
@IBOutlet private weak var prefixArrowIcon: UIImageView!
@IBOutlet private weak var prefixArrowIcon_width: NSLayoutConstraint! //8
@IBOutlet private weak var prefixArrowIcon_height: NSLayoutConstraint! //4
@IBOutlet private weak var prefixButton: UIButton!
@IBOutlet private weak var textFieldView: UIView!
@IBOutlet var textField: KNTextField!
@IBOutlet private weak var textField_trailing: NSLayoutConstraint! //12
@IBOutlet private weak var unitValueLabel: UILabel!
@IBOutlet private weak var accessoryView: UIView!
@IBOutlet private weak var accessoryViewLabel: UILabel!
@IBOutlet private weak var accessoryViewIcon: UIImageView!
@IBOutlet private weak var accessoryView_width: NSLayoutConstraint!
@IBOutlet private weak var accessoryView_trailing: NSLayoutConstraint!
@IBOutlet private weak var accessory_button: UIButton!
@IBOutlet private weak var unitMeasurementDropdwonArrowImageView: UIImageView!
@IBOutlet private weak var unitMeasurementDropdwonArrowImageView_width: NSLayoutConstraint!
@IBOutlet private weak var unitMeasurementDropdwonArrowImageView_height: NSLayoutConstraint!
// bottom
@IBOutlet private weak var bottomView: UIView!
@IBOutlet private weak var infoLabel: UILabel!
@IBOutlet private weak var infoLabel_top: NSLayoutConstraint!
@IBOutlet private weak var button: UIButton!
// userName label
@IBOutlet private weak var useNameLabel: UILabel!
@IBOutlet private weak var userNameLabel_width: NSLayoutConstraint!
@IBOutlet weak var userNameLabel_trailing: NSLayoutConstraint!
@IBOutlet weak var userNameLabel_leading: NSLayoutConstraint!
@IBOutlet weak var textField_leading: NSLayoutConstraint!
// MARK: - Properties
private var helper: KNTextFieldViewHelper?
private var disposeBag = DisposeBag()
var field: KNField?
var unitValueField: KNTextFieldView?
var isUnitMeasurement: (value: Bool, dropdown: Bool) = (value: false, dropdown: false)
weak var delegate: KNTextFieldViewDelegate?
weak var dropdownDelegate: KNTextFieldViewDropdownDelegate?
weak var prefixDelegate: KNTextFieldViewPrefixDelegate?
// MARK: - Lifecycle
override func setupNib() {
super.setupNib()
view.frame = bounds
view.autoresizingMask = [.flexibleHeight, .flexibleWidth]
setupUI()
}
// MARK: - UI
func setupUI() {
backgroundColor = .clear
view.backgroundColor = .clear
boxView.backgroundColor = .clear
topView.backgroundColor = .clear
fieldView.backgroundColor = .clear
borderView.backgroundColor = .white
prefixView.backgroundColor = .clear
textFieldView.backgroundColor = .clear
accessoryView.backgroundColor = .clear
textField.backgroundColor = .clear
bottomView.backgroundColor = .clear
titleLabel_bottom.set(0) //8
prefixView_width.set(0) //100
accessoryView_width.set(0) //50
infoLabel_top.set(0) //8a
useNameLabel.set(text: "")
useNameLabel.hide()
userNameLabel_width.set(0)
userNameLabel_trailing.set(0)
userNameLabel_leading.set(0)
textField_leading.set(12)
borderView.addBorder(radius: 13, width: 1, color: .purple)
titleLabel.set(text: "", color: .black, font: .semibold(12))
titleLabel.numberOfLines = 1
infoLabel.set(text: "", color: .black, font: .regular(12))
infoLabel.numberOfLines = 0
countLabel.set(text: "", color: .purple, font: .medium(12))
countLabel.numberOfLines = 1
countLabel.align(to: .left)
unitValueLabel.hide()
textField.text = ""
textField.placeholder = ""
textField.delegate = self
textField.isUserInteractionEnabled = true
textField.tintColor = .purple
textField.textAlignment = .left
accessoryViewLabel.set(text: "", color: .gray, font: .medium(16))
accessoryViewLabel.numberOfLines = 1
accessory_button.isUserInteractionEnabled = false
accessory_button.addTarget(self, action: #selector(accessoryButtonTapped), for: .touchUpInside)
accessoryView.hide()
accessoryViewIcon.hide()
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
button.isUserInteractionEnabled = false
button.hide()
}
override func layoutSubviews() {
super.layoutSubviews()
//rtl
//@TODO @RTL-ISSUE
//everything is fine when we have layoustsubvies in textfield.
// not working properly here. play around to find a solution
//textField.textAlignment = lang == .en ? .right : .left
//textField.semanticContentAttribute = lang == .en ? .forceRightToLeft : .forceLeftToRight
}
// MARK: - Setup
func set(field: KNField?) {
self.field = field
textField.textAlignment = .left
textField.semanticContentAttribute = .forceLeftToRight
updateUI()
}
// MARK: - Handlers
private func updateUI() {
guard let field = field else { return }
// helper
helper = KNTextFieldViewHelper(field: field)
guard let helper = helper else { return }
//
borderView.addBorder(radius: 13, width: 1, color: .purple)
textField.textAlignment = .left
textField.semanticContentAttribute = .forceLeftToRight
titleLabel.text = field.title == "" ? helper.title : field.title
titleLabel_bottom.set(8)
countLabel.text = ""
countLabel.hide()
// field
textField.keyboardType = helper.keyboard
textField.returnKeyType = helper.returnKey
textField.isSecureTextEntry = helper.secureEntry
if field.field == .iban {
textField.autocapitalizationType = .allCharacters
}
if field.field == .price || field.field == .sale_price {
textField.keyboardType = .decimalPad
}
//
// if field.hasPlaceholder {
// if isUnitMeasurement.dropdown {
// //textField.placeholder = field.unitMeasurement?.display ?? ""
// } else {
// if field.isArabic {
// textField.setForArabic(localizedPlaceholder: field.placeholder != "" ? field.placeholder.localized : helper.placeholder, color: .placeholder, font: .regular(16))
// } else if field.isEnglish {
// textField.setForEnglighs(localizedPlaceholder: field.placeholder != "" ? field.placeholder.localized : helper.placeholder, color: .placeholder, font: .regular(16))
// } else {
// if field.placeholder == "" {
// textField.set(localizedPlaceholder: field.placeholder != "" ? field.placeholder.localized : helper.placeholder, color: .placeholder, font: .regular(16))
// } else {
// textField.set(localizedPlaceholder: field.placeholder != "" ? field.placeholder.localized : helper.placeholder, color: .placeholder, font: .regular(16))
// }
// }
// }
// } else {
// textField.placeholder = ""
// }
textField.show()
unitValueLabel.hide()
textField.text = field.value.value
// if field.isArabic {
// textField.textAlignment = lang == .en ? .right : .left
// textFieldView.semanticContentAttribute = lang == .en ? .forceRightToLeft : .forceLeftToRight
// } else {
// textField.textAlignment = lang == .en ? .left : .right
// textFieldView.semanticContentAttribute = lang == .en ? .forceLeftToRight : .forceRightToLeft
//
// }
// field.unitValue.observe { [weak self] unit in
// guard let strongSelf = self else { return }
//
// strongSelf.borderView.addBorder(radius: 13,
// width: 1,
// color: .border)
//
// //strongSelf.textField.set(text: unit,
//// color: .placeholder,
//// font: .regular(16))
// strongSelf.unitValueLabel.show()
// strongSelf.unitValueLabel.set(text: unit,
// color: .red,
// font: .regular(16))
// print("putin", self?.field?.isUnitMeasurement, self?.isUnitMeasurement)
// print(strongSelf.unitValueField?.field?.value.value)
// print(strongSelf.unitValueField?.field?.unitValue.value)
// }.disposed(by: disposeBag)
if !isUnitMeasurement.dropdown {
unitValueLabel.hide()
field.value.observe { [weak self] text in
guard let strongSelf = self else { return }
strongSelf.textField.text = text
if text.count > 0 {
strongSelf.borderView.addBorder(radius: 13,
width: 2,
color: .purple)
if strongSelf.field?.field != .email || strongSelf.field?.field != .shipping_address_email || strongSelf.field?.field != .billing_address_email {
strongSelf.field?.error.value = ""
}
} else {
//@TODO: check the reset thign again(no reload/updates?)
strongSelf.resetTextField()
}
}.disposed(by: disposeBag)
textField.bind { [weak self] binded in
guard let strongSelf = self else { return }
var text = binded
field.value.value = text
if text.count > 0 {
strongSelf.borderView.addBorder(radius: 13, width: 2, color: .purple)
}
//strongSelf.validate()
if text.count == 0 {
//@TODO no reset necessary?
strongSelf.resetTextField()
}
strongSelf.delegate?.updateUI(for: field)
}
textField.endEditingBind { [weak self] endEditingBinded in
guard let strongSelf = self else { return }
strongSelf.validate()
strongSelf.delegate?.updateUI(for: field)
}
}
// ////////////////////////////////// //
// accessory
if field.field == .password || field.field == .confirm_password || field.field == .old_password {
accessoryView_width.set(50)
accessoryView.show()
accessoryViewIcon.show()
accessory_button.show()
accessory_button.isUserInteractionEnabled = true
}
// info
if field.error.value.count > 0 {
if isUnitMeasurement.dropdown { return }
set(error: field.error.value)
} else {
infoLabel_top.set(0)
infoLabel.text = ""
}
field.error.observe { [weak self] text in
guard let strongSelf = self else { return }
if strongSelf.isUnitMeasurement.dropdown { return }
if text.count > 0 {
strongSelf.borderView.addBorder(radius: 13, width: 2, color: .purple)
strongSelf.set(error: text)
strongSelf.delegate?.updateUI(for: field)
}
if text.count == 0 {
//@TODO: reset the field but without any update
// test more for ERROR case
strongSelf.resetTextField()
}
}.disposed(by: disposeBag)
// ////////////////
// extra settings
if isUnitMeasurement.dropdown {
textField.isUserInteractionEnabled = false
}
if field.editable {
textField.isUserInteractionEnabled = true
} else {
textField.isUserInteractionEnabled = false
}
// update field
if let text = textField.text {
if isUnitMeasurement.dropdown { return }
if text.count > 0 {
borderView.addBorder(radius: 13, width: 2, color: .purple)
}
}
textField.textAlignment = .left
textField.semanticContentAttribute = .forceLeftToRight
}
// MARK: - Handler
@objc private func buttonTapped() {
}
@objc private func prefixTapped() {
}
@objc private func accessoryButtonTapped() {
}
//@TODO @bibi add network error field
}
// MARK: - UI Helpers - Error
extension KNTextFieldView {
private func validate() {
guard let field = field else { return }
if field.field == .email || field.field == .shipping_address_email || field.field == .billing_address_email{
guard let text = textField.text else { return }
if text.isValidEmail {
field.error.value = ""
//@TODO reset func
//resetTextField()
} else {
field.error.value = helper?.error ?? ""
set(error: helper?.error)
}
}
}
private func set(error: String?) {
guard let error = error else { return }
if isUnitMeasurement.dropdown { return }
infoLabel_top.set(8)
infoLabel.set(localized: error, color: .red, font: .regular(12))
borderView.addBorder(radius: 13, width: 2, color: .red)
textField.textAlignment = .left
}
private func resetTextField() {
if isUnitMeasurement.dropdown { return }
guard let field = field else { return }
textField.textAlignment = .left
textField.semanticContentAttribute = .forceLeftToRight
// textField.textAlignment = lang == .en ? .left : .right
// textField.semanticContentAttribute = lang == .en ? .forceLeftToRight : .forceRightToLeft
//
set(field: field)
}
}
// MARK: - TextField Delegate
extension KNTextFieldView: UITextFieldDelegate {
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
guard let field = field else { return true }
if field.field == .sale_start_date || field.field == .sale_end_date {
return false
}
return true
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let field = field else { return true }
if field.field == .password || field.field == .confirm_password || field.field == .old_password {
if let textFieldString = textField.text {
let nsString = NSString(string: textFieldString)
let updatedString = nsString.replacingCharacters(in:range, with:string)
textField.text = updatedString
//Setting the cursor at the right place
let selectedRange = NSMakeRange(range.location + string.count, 0)
let from = textField.position(from: textField.beginningOfDocument, offset:selectedRange.location)
let to = textField.position(from: from!, offset:selectedRange.length)
textField.selectedTextRange = textField.textRange(from: from!, to: to!)
//Sending an action
textField.sendActions(for: .editingChanged)
return false
}
return true
}
return false
}
func textFieldDidEndEditing(_ textField: UITextField) {
//@TODO this is not ok as well
//we could reset (but without the update(reload)
resetTextField()
}
}
This diff is collapsed.
//
// KNTextFieldViewHelper.swift
// traccar
//
// Created by iOS Developer on 2/7/22.
//
import Foundation
import UIKit
import Alamofire
final class KNTextFieldViewHelper {
private var type: KNFieldType = .empty
private var field: JSONField = .none
// MARK: - Init
init(field: KNField) {
self.type = field.type
self.field = field.field
}
// MARK: - UI
let labelPadding: CGFloat = 8
// MARK: - Localization
var title: String {
return ""
}
var placeholder: String {
return ""
}
var error: String {
return ""
}
// keyboard type
var keyboard: UIKeyboardType {
let units: [JSONField] = [
.weight, .width, .height, .length
]
if units.contains(field) {
return .decimalPad
}
switch field {
case .phone, .shipping_address_phone, .billing_address_phone:
return .phonePad
case .email, .shipping_address_email, .billing_address_email:
return .emailAddress
case .block,
.billing_address_block,
.shipping_address_block,
.avenue,
.billing_address_avenue,
.shipping_address_avenue,
.floor,
.billing_address_floor,
.shipping_address_floor:
return .numberPad
default:
return .default
}
}
// field is password
var secureEntry: Bool {
switch field {
case .password, .confirm_password, .old_password :
return true
default:
return false
}
}
// return key (next or done)
var returnKey: UIReturnKeyType {
switch field {
case .phone:
return .done
default:
return .next
}
}
}
//
// KNField.swift
//
//
// Created by iOS Developer on 2/7/22.
//
import Foundation
import UIKit
final class KNField {
typealias KNFieldBuilderClosure = (KNFieldBuilder) -> Void
// MARK: - Properties
var type: KNFieldType = .empty
var tag: KNFieldTag = .none
var field: JSONField = .none
var isRequired: Bool = false
var value: Observable<String> = Observable("")
var info: Observable<String> = Observable("")
var error: Observable<String> = Observable("")
var title: String = ""
var height: CGFloat = .automatic
var hidden: Bool = false
var enabled: Bool = true
var editable: Bool = true
var labelStyle: KNLableStyle = .simple
var allignment: NSTextAlignment = .natural
// MARK: - Init
init() { }
init(builder: KNFieldBuilder) {
isRequired = builder.isRequired
field = builder.field
type = builder.type
tag = builder.tag
value.value = builder.value
error.value = builder.error
info.value = builder.info
height = builder.height
title = builder.title
enabled = builder.enabled
editable = builder.editable
labelStyle = builder.labelStyle
allignment = builder.allignment
hidden = builder.hidden
}
convenience init(_ block: KNFieldBuilderClosure) {
let builder = KNFieldBuilder()
block(builder)
self.init(builder: builder)
}
// MARK: - Helper
// MARK: - JSON Param
var param: PARAMS {
var json: PARAMS = [:]
guard field != .none else { return [:] }
guard !hidden else { return [:] }
switch type {
case .text, .empty:
if !value.value.isEmpty {
json.add(key: field, value.value)
}
}
return json
}
}
//
// KNFieldBuilder.swift
// traccar
//
// Created by iOS Developer on 2/7/22.
//
import Foundation
import UIKit
enum KNLableStyle {
case simple
case colored_text
}
final class KNFieldBuilder {
// MARK: - Properties
var tag: KNFieldTag = .none
var type: KNFieldType = .empty
var field: JSONField = .none
var isRequired: Bool = false
var title: String = ""
var value: String = ""
var error: String = ""
var info: String = ""
var height: CGFloat = .automatic
var enabled: Bool = true
var editable: Bool = true
var hidden: Bool = false
var labelStyle: KNLableStyle = .simple
var allignment: NSTextAlignment = .natural
// MARK: - Init
init() {
}
}
//
// KNFieldDropDownAddressObjectProtocol.swift
// traccar
//
// Created by George Makhoul on 9/15/22.
//
import Foundation
protocol KNFieldDropDownAddressObjectProtocol {
var iden: String? { get }
var name: String { get }
var formattedName: String { get }
var phone_number: String { get }
}
//
// KNFieldDropdownObjectProtocol.swift
// traccar
//
// Created by iOS Developer on 4/3/22.
//
import Foundation
protocol KNFieldDropdownObjectProtocol {
var identifier: String? { get }
var name: String { get }
var formattedName: String { get }
}
//
// KNFieldType.swift
// traccar
//
// Created by iOS Developer on 2/7/22.
//
import Foundation
enum KNFieldTag {
case none
case spaceToNext
}
enum KNFieldType {
case empty
case text
}
//
// CGFLoat.swift
// TraccarClient
//
// Created by George Makhoul on 25/10/2023.
// Copyright © 2023 Traccar. All rights reserved.
//
import UIKit
extension CGFloat {
static let automatic: CGFloat = UITableView.automaticDimension
static let dynamic: CGFloat = 0
}
//
// Dictionary.swift
// TraccarClient
//
// Created by George Makhoul on 25/10/2023.
// Copyright © 2023 Traccar. All rights reserved.
//
import Foundation
extension Dictionary where Key: ExpressibleByStringLiteral {
// Custom enum keys
subscript<Index: RawRepresentable>(index: Index) -> Value? where Index.RawValue == String {
get {
return self["\(index.rawValue.lowercased())" as! Key]
}
set {
self["\(index.rawValue.lowercased())" as! Key] = newValue
}
}
}
extension Dictionary where Key == String, Value == Any {
mutating func add(key: JSONField, _ value: Any?) {
if let string = value as? String {
self[key.rawValue] = string
} else if let int = value as? Int {
self[key.rawValue] = int
} else if let double = value as? Double {
self[key.rawValue] = double
} else if let objects = value as? [JSON] {
self[key.rawValue] = objects
} else if let object = value as? JSON {
self[key.rawValue] = object
} else if value != nil {
self[key.rawValue] = value
}
}
mutating func add(_ k: String, _ value: Any?) {
if let string = value as? String {
self[k] = string
} else if let int = value as? Int {
self[k] = int
} else if let double = value as? Double {
self[k] = double
} else if value != nil {
self[k] = value
}
}
mutating func add(_ params: PARAMS) {
for (k, v) in params {
add(k, v)
}
}
mutating func add(jsons: [JSON]) {
for json in jsons {
for (k, v) in json {
add(k, v)
}
}
}
func string(_ key: JSONField) -> String {
if let str = self[key.rawValue] as? String {
return str
}
return ""
}
func dictionary(_ key: JSONField) -> JSON {
if let dict = self[key.rawValue] as? JSON {
return dict
}
return [:]
}
func dictionaries(_ key: JSONField) -> [JSON]? {
if let dicts = self[key.rawValue] as? [JSON] {
return dicts
}
return nil
}
func bool(_ key: JSONField) -> Bool {
if let bool = self[key.rawValue] as? Bool {
return bool
}
return false
}
func int(_ key: JSONField) -> Int {
if let int = self[key.rawValue] as? Int {
return int
}
if let str = self[key.rawValue] as? String {
if let int = Int(str) {
return int
}
return 0
}
return 0
}
}
{
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Delivery service.pdf",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment