diff --git a/TraccarClient.xcodeproj/project.pbxproj b/TraccarClient.xcodeproj/project.pbxproj index f57835edeb6b4c0b30f3cae68bd9806b507bf426..2f1574112a659ec574b01779120ed09d6b9a56e3 100644 --- a/TraccarClient.xcodeproj/project.pbxproj +++ b/TraccarClient.xcodeproj/project.pbxproj @@ -64,6 +64,12 @@ 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 */; }; + 532683BB2AEA50B800A364C0 /* LoginDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683BA2AEA50B800A364C0 /* LoginDataSource.swift */; }; + 532683BD2AEA50C600A364C0 /* LoginModelController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683BC2AEA50C600A364C0 /* LoginModelController.swift */; }; + 532683BF2AEA50EF00A364C0 /* LoginDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683BE2AEA50EF00A364C0 /* LoginDataProvider.swift */; }; + 532683C12AEA50FA00A364C0 /* LoginViewControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683C02AEA50FA00A364C0 /* LoginViewControllerProtocol.swift */; }; + 532683C32AEA537F00A364C0 /* UITableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532683C22AEA537F00A364C0 /* UITableView.swift */; }; + 532683C82AEA631800A364C0 /* IQKeyboardManagerSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 532683C72AEA631800A364C0 /* IQKeyboardManagerSwift */; }; 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 */; }; @@ -177,6 +183,11 @@ 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>"; }; + 532683BA2AEA50B800A364C0 /* LoginDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginDataSource.swift; sourceTree = "<group>"; }; + 532683BC2AEA50C600A364C0 /* LoginModelController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginModelController.swift; sourceTree = "<group>"; }; + 532683BE2AEA50EF00A364C0 /* LoginDataProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginDataProvider.swift; sourceTree = "<group>"; }; + 532683C02AEA50FA00A364C0 /* LoginViewControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewControllerProtocol.swift; sourceTree = "<group>"; }; + 532683C22AEA537F00A364C0 /* UITableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITableView.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>"; }; @@ -252,6 +263,7 @@ 532683812AE923DE00A364C0 /* Alamofire in Frameworks */, CED4871C17DB1BF6007FCF57 /* UIKit.framework in Frameworks */, 5EE3CA362998948F002C86E4 /* FirebaseCrashlytics in Frameworks */, + 532683C82AEA631800A364C0 /* IQKeyboardManagerSwift in Frameworks */, 5EE3CA39299894B9002C86E4 /* InAppSettingsKit in Frameworks */, CED4871E17DB1BF6007FCF57 /* Foundation.framework in Frameworks */, CED4872017DB1BF6007FCF57 /* CoreGraphics.framework in Frameworks */, @@ -271,11 +283,9 @@ 532683392AE9174700A364C0 /* Views */ = { isa = PBXGroup; children = ( - 532683822AE928F900A364C0 /* KNTableViewCell.swift */, - 532683662AE923A500A364C0 /* BMTextFieldView */, - 5326833A2AE9175900A364C0 /* LoginViewController.swift */, - 5326833B2AE9175900A364C0 /* LoginViewController.xib */, - 532683842AE9293200A364C0 /* KNComponentView.swift */, + 532683C52AEA5DDF00A364C0 /* Custom */, + CED4873317DB1BF6007FCF57 /* MainStoryboard.storyboard */, + CEF643241B919FFA00195CEA /* LaunchScreen.xib */, ); name = Views; sourceTree = "<group>"; @@ -322,6 +332,7 @@ 532683AE2AE94C2F00A364C0 /* NSLayoutConstraints.swift */, 532683B02AE94C9400A364C0 /* Dictionary.swift */, 532683B22AE98D0000A364C0 /* UILabel.swift */, + 532683C22AEA537F00A364C0 /* UITableView.swift */, ); name = helpers; sourceTree = "<group>"; @@ -376,6 +387,61 @@ name = Network; sourceTree = "<group>"; }; + 532683B62AEA505C00A364C0 /* LoginViewController */ = { + isa = PBXGroup; + children = ( + 532683B92AEA508300A364C0 /* Controller */, + 532683B82AEA507900A364C0 /* View */, + 532683B72AEA507300A364C0 /* Model */, + ); + path = LoginViewController; + sourceTree = "<group>"; + }; + 532683B72AEA507300A364C0 /* Model */ = { + isa = PBXGroup; + children = ( + 532683BA2AEA50B800A364C0 /* LoginDataSource.swift */, + 532683BC2AEA50C600A364C0 /* LoginModelController.swift */, + 532683BE2AEA50EF00A364C0 /* LoginDataProvider.swift */, + 532683C02AEA50FA00A364C0 /* LoginViewControllerProtocol.swift */, + ); + path = Model; + sourceTree = "<group>"; + }; + 532683B82AEA507900A364C0 /* View */ = { + isa = PBXGroup; + children = ( + 5326833B2AE9175900A364C0 /* LoginViewController.xib */, + ); + path = View; + sourceTree = "<group>"; + }; + 532683B92AEA508300A364C0 /* Controller */ = { + isa = PBXGroup; + children = ( + 5326833A2AE9175900A364C0 /* LoginViewController.swift */, + ); + path = Controller; + sourceTree = "<group>"; + }; + 532683C42AEA5DB000A364C0 /* Controllers */ = { + isa = PBXGroup; + children = ( + 532683B62AEA505C00A364C0 /* LoginViewController */, + ); + name = Controllers; + sourceTree = "<group>"; + }; + 532683C52AEA5DDF00A364C0 /* Custom */ = { + isa = PBXGroup; + children = ( + 532683842AE9293200A364C0 /* KNComponentView.swift */, + 532683822AE928F900A364C0 /* KNTableViewCell.swift */, + 532683662AE923A500A364C0 /* BMTextFieldView */, + ); + path = Custom; + sourceTree = "<group>"; + }; CED4870F17DB1BF6007FCF57 = { isa = PBXGroup; children = ( @@ -412,14 +478,13 @@ CED4872117DB1BF6007FCF57 /* TraccarClient */ = { isa = PBXGroup; children = ( + CB7ED0831F662BAF00A33FCF /* AppDelegate.swift */, + 532683C42AEA5DB000A364C0 /* Controllers */, 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 */, 5E716A261F63A0B100A2DBC3 /* DistanceCalculator.swift */, CBAA0F7E1F68E807008BBBBE /* MainViewController.swift */, @@ -491,6 +556,7 @@ 5EE3CA38299894B9002C86E4 /* InAppSettingsKit */, 532683802AE923DE00A364C0 /* Alamofire */, 5326839E2AE9489C00A364C0 /* Reachability */, + 532683C72AEA631800A364C0 /* IQKeyboardManagerSwift */, ); productName = TraccarClient; productReference = CED4871817DB1BF6007FCF57 /* TraccarClient.app */; @@ -559,6 +625,7 @@ 5EE3CA37299894B9002C86E4 /* XCRemoteSwiftPackageReference "InAppSettingsKit" */, 5326837F2AE923DE00A364C0 /* XCRemoteSwiftPackageReference "Alamofire" */, 5326839D2AE9489C00A364C0 /* XCRemoteSwiftPackageReference "Reachability" */, + 532683C62AEA631800A364C0 /* XCRemoteSwiftPackageReference "IQKeyboardManager" */, ); productRefGroup = CED4871917DB1BF6007FCF57 /* Products */; projectDirPath = ""; @@ -640,6 +707,7 @@ 532683962AE9482300A364C0 /* Network+Endpoint.swift in Sources */, CB7ED0801F6602CD00A33FCF /* Position.swift in Sources */, 532683972AE9482300A364C0 /* Network+Result.swift in Sources */, + 532683BB2AEA50B800A364C0 /* LoginDataSource.swift in Sources */, 5326837A2AE923A500A364C0 /* KNFieldDropDownAddressObjectProtocol.swift in Sources */, CBAA0F7F1F68E807008BBBBE /* MainViewController.swift in Sources */, 532683B52AE98FB600A364C0 /* UIString.swift in Sources */, @@ -668,6 +736,7 @@ CBAA0F7D1F68E14C008BBBBE /* StatusViewController.swift in Sources */, 532683A72AE94ADC00A364C0 /* KNObject.swift in Sources */, 532683A12AE948FF00A364C0 /* AppManager.swift in Sources */, + 532683C12AEA50FA00A364C0 /* LoginViewControllerProtocol.swift in Sources */, 532683A32AE9497100A364C0 /* Keys.swift in Sources */, 532683A92AE94B1300A364C0 /* UIInt.swift in Sources */, 5326837D2AE923A500A364C0 /* KNFieldBuilder.swift in Sources */, @@ -677,10 +746,13 @@ 5E716A271F63A0B100A2DBC3 /* DistanceCalculator.swift in Sources */, 532683792AE923A500A364C0 /* FieldTableViewCell.swift in Sources */, 5326838B2AE92CA500A364C0 /* JSONField.swift in Sources */, + 532683BF2AEA50EF00A364C0 /* LoginDataProvider.swift in Sources */, 532683892AE92B6800A364C0 /* Observable.swift in Sources */, + 532683BD2AEA50C600A364C0 /* LoginModelController.swift in Sources */, 5326837B2AE923A500A364C0 /* KNFieldType.swift in Sources */, 532683B12AE94C9400A364C0 /* Dictionary.swift in Sources */, 5E716A291F63A45A00A2DBC3 /* RequestManager.swift in Sources */, + 532683C32AEA537F00A364C0 /* UITableView.swift in Sources */, 5326839B2AE9482300A364C0 /* NetworkRequest.swift in Sources */, CB4197931F674A3E008F301C /* DatabaseHelper.swift in Sources */, ); @@ -1167,6 +1239,14 @@ kind = branch; }; }; + 532683C62AEA631800A364C0 /* XCRemoteSwiftPackageReference "IQKeyboardManager" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/hackiftekhar/IQKeyboardManager"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 6.5.16; + }; + }; 5EE3CA322998948F002C86E4 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/firebase/firebase-ios-sdk"; @@ -1196,6 +1276,11 @@ package = 5326839D2AE9489C00A364C0 /* XCRemoteSwiftPackageReference "Reachability" */; productName = Reachability; }; + 532683C72AEA631800A364C0 /* IQKeyboardManagerSwift */ = { + isa = XCSwiftPackageProductDependency; + package = 532683C62AEA631800A364C0 /* XCRemoteSwiftPackageReference "IQKeyboardManager" */; + productName = IQKeyboardManagerSwift; + }; 5EE3CA332998948F002C86E4 /* FirebaseAnalytics */ = { isa = XCSwiftPackageProductDependency; package = 5EE3CA322998948F002C86E4 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; diff --git a/TraccarClient.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/TraccarClient.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d5843b2df106c54f5924be5431ba7da11dc596b9..c2746fdab1021ccf7053be9a7e6e8c138e119a8c 100644 --- a/TraccarClient.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/TraccarClient.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -90,6 +90,15 @@ "revision" : "08ab93cd15759eed534b821c2ea789d97a0fdca0" } }, + { + "identity" : "iqkeyboardmanager", + "kind" : "remoteSourceControl", + "location" : "https://github.com/hackiftekhar/IQKeyboardManager", + "state" : { + "revision" : "c00b1ae9fa1ad8af4465bb6ca901f6943fc98eba", + "version" : "6.5.16" + } + }, { "identity" : "leveldb", "kind" : "remoteSourceControl", diff --git a/TraccarClient.xcodeproj/project.xcworkspace/xcuserdata/g.makhoul.xcuserdatad/UserInterfaceState.xcuserstate b/TraccarClient.xcodeproj/project.xcworkspace/xcuserdata/g.makhoul.xcuserdatad/UserInterfaceState.xcuserstate index 6dbcabd5844afbb03adf75842a087fbf84e62c43..a4e7006af8b5ad8b450324f2da661967ad272ba0 100644 Binary files a/TraccarClient.xcodeproj/project.xcworkspace/xcuserdata/g.makhoul.xcuserdatad/UserInterfaceState.xcuserstate and b/TraccarClient.xcodeproj/project.xcworkspace/xcuserdata/g.makhoul.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/TraccarClient/AppDelegate.swift b/TraccarClient/AppDelegate.swift index 732da69387cb905f29992dd42d94f687961a90db..173dcfee0cd51c8f3ab1fa5b70d015e1816d9dcc 100644 --- a/TraccarClient/AppDelegate.swift +++ b/TraccarClient/AppDelegate.swift @@ -17,6 +17,7 @@ import UIKit import CoreData import Firebase +import IQKeyboardManagerSwift @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, PositionProviderDelegate { @@ -67,10 +68,27 @@ class AppDelegate: UIResponder, UIApplicationDelegate, PositionProviderDelegate trackingController = TrackingController() trackingController?.start() } + + IQKeyboardManager.shared.enable = true + IQKeyboardManager.shared.shouldResignOnTouchOutside = true + IQKeyboardManager.shared.previousNextDisplayMode = .alwaysShow + IQKeyboardManager.shared.toolbarTintColor = .purple + + setRootNavigation() return true } + func setRootNavigation() { + window = UIWindow(frame: UIScreen.main.bounds) + + let vc = LoginViewController() + vc.window = window + + window?.rootViewController = vc + window?.makeKeyAndVisible() + } + func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) { let userDefaults = UserDefaults.standard diff --git a/TraccarClient/BMTextFieldView/Cell/FieldTableViewCell.swift b/TraccarClient/Custom/BMTextFieldView/Cell/FieldTableViewCell.swift similarity index 100% rename from TraccarClient/BMTextFieldView/Cell/FieldTableViewCell.swift rename to TraccarClient/Custom/BMTextFieldView/Cell/FieldTableViewCell.swift diff --git a/TraccarClient/BMTextFieldView/Cell/FieldTableViewCell.xib b/TraccarClient/Custom/BMTextFieldView/Cell/FieldTableViewCell.xib similarity index 100% rename from TraccarClient/BMTextFieldView/Cell/FieldTableViewCell.xib rename to TraccarClient/Custom/BMTextFieldView/Cell/FieldTableViewCell.xib diff --git a/TraccarClient/BMTextFieldView/KNTextFieldView+Protocols.swift b/TraccarClient/Custom/BMTextFieldView/KNTextFieldView+Protocols.swift similarity index 100% rename from TraccarClient/BMTextFieldView/KNTextFieldView+Protocols.swift rename to TraccarClient/Custom/BMTextFieldView/KNTextFieldView+Protocols.swift diff --git a/TraccarClient/BMTextFieldView/KNTextFieldView.swift b/TraccarClient/Custom/BMTextFieldView/KNTextFieldView.swift similarity index 99% rename from TraccarClient/BMTextFieldView/KNTextFieldView.swift rename to TraccarClient/Custom/BMTextFieldView/KNTextFieldView.swift index 45e13099f10f44a40e7685b615ab66a392c7486b..3002cef10bc85e5b1fa207a303ec23bb059062b1 100644 --- a/TraccarClient/BMTextFieldView/KNTextFieldView.swift +++ b/TraccarClient/Custom/BMTextFieldView/KNTextFieldView.swift @@ -468,7 +468,7 @@ extension KNTextFieldView: UITextFieldDelegate { return true } - return false + return true } func textFieldDidEndEditing(_ textField: UITextField) { diff --git a/TraccarClient/BMTextFieldView/KNTextFieldView.xib b/TraccarClient/Custom/BMTextFieldView/KNTextFieldView.xib similarity index 100% rename from TraccarClient/BMTextFieldView/KNTextFieldView.xib rename to TraccarClient/Custom/BMTextFieldView/KNTextFieldView.xib diff --git a/TraccarClient/BMTextFieldView/KNTextFieldViewHelper.swift b/TraccarClient/Custom/BMTextFieldView/KNTextFieldViewHelper.swift similarity index 100% rename from TraccarClient/BMTextFieldView/KNTextFieldViewHelper.swift rename to TraccarClient/Custom/BMTextFieldView/KNTextFieldViewHelper.swift diff --git a/TraccarClient/BMTextFieldView/Model/KNField.swift b/TraccarClient/Custom/BMTextFieldView/Model/KNField.swift similarity index 100% rename from TraccarClient/BMTextFieldView/Model/KNField.swift rename to TraccarClient/Custom/BMTextFieldView/Model/KNField.swift diff --git a/TraccarClient/BMTextFieldView/Model/KNFieldBuilder.swift b/TraccarClient/Custom/BMTextFieldView/Model/KNFieldBuilder.swift similarity index 100% rename from TraccarClient/BMTextFieldView/Model/KNFieldBuilder.swift rename to TraccarClient/Custom/BMTextFieldView/Model/KNFieldBuilder.swift diff --git a/TraccarClient/BMTextFieldView/Model/KNFieldDropDownAddressObjectProtocol.swift b/TraccarClient/Custom/BMTextFieldView/Model/KNFieldDropDownAddressObjectProtocol.swift similarity index 100% rename from TraccarClient/BMTextFieldView/Model/KNFieldDropDownAddressObjectProtocol.swift rename to TraccarClient/Custom/BMTextFieldView/Model/KNFieldDropDownAddressObjectProtocol.swift diff --git a/TraccarClient/BMTextFieldView/Model/KNFieldDropdownObjectProtocol.swift b/TraccarClient/Custom/BMTextFieldView/Model/KNFieldDropdownObjectProtocol.swift similarity index 100% rename from TraccarClient/BMTextFieldView/Model/KNFieldDropdownObjectProtocol.swift rename to TraccarClient/Custom/BMTextFieldView/Model/KNFieldDropdownObjectProtocol.swift diff --git a/TraccarClient/BMTextFieldView/Model/KNFieldType.swift b/TraccarClient/Custom/BMTextFieldView/Model/KNFieldType.swift similarity index 100% rename from TraccarClient/BMTextFieldView/Model/KNFieldType.swift rename to TraccarClient/Custom/BMTextFieldView/Model/KNFieldType.swift diff --git a/TraccarClient/KNComponentView.swift b/TraccarClient/Custom/KNComponentView.swift similarity index 100% rename from TraccarClient/KNComponentView.swift rename to TraccarClient/Custom/KNComponentView.swift diff --git a/TraccarClient/KNTableViewCell.swift b/TraccarClient/Custom/KNTableViewCell.swift similarity index 100% rename from TraccarClient/KNTableViewCell.swift rename to TraccarClient/Custom/KNTableViewCell.swift diff --git a/TraccarClient/JSONField.swift b/TraccarClient/JSONField.swift index 9e7f1246c91dd0e28a31c4b325836da88d740cb1..0ca1fc2a2ea927afcbccb31ff9e26b296addf858 100644 --- a/TraccarClient/JSONField.swift +++ b/TraccarClient/JSONField.swift @@ -80,7 +80,7 @@ enum JSONField: String { case option case confirm_password case code - case username = "user_name" + case username = "username" case business = "business_name" case dynamicSpace case old_password @@ -118,7 +118,6 @@ enum JSONField: String { case addresses = "address" case processing_times = "processing_time" case freeShipping = "free_shipping" - case authUsername = "username" case authBusiness = "business" case handling_fees diff --git a/TraccarClient/LoginViewController.swift b/TraccarClient/LoginViewController.swift deleted file mode 100644 index e87d9066daca558982b97cbe766937a8a8fa60dd..0000000000000000000000000000000000000000 --- a/TraccarClient/LoginViewController.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// LoginViewController.swift -// TraccarClient -// -// Created by George Makhoul on 25/10/2023. -// Copyright © 2023 Traccar. All rights reserved. -// - -import UIKit - -final class LoginViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - } - -} diff --git a/TraccarClient/LoginViewController/Controller/LoginViewController.swift b/TraccarClient/LoginViewController/Controller/LoginViewController.swift new file mode 100644 index 0000000000000000000000000000000000000000..00085c326ed36f200cf5a4b5bec9dd524f823feb --- /dev/null +++ b/TraccarClient/LoginViewController/Controller/LoginViewController.swift @@ -0,0 +1,59 @@ +// +// LoginViewController.swift +// TraccarClient +// +// Created by George Makhoul on 25/10/2023. +// Copyright © 2023 Traccar. All rights reserved. +// + +import UIKit + +final class LoginViewController: UIViewController { + // MARK: - Outlets + @IBOutlet private weak var tableView: UITableView! + + // MARK: - Properties + private weak var delegate: LoginViewControllerDelegate? + + private var modelDataSource: LoginDataSource? + private var modelController: LoginModelController? + var window: UIWindow? + + // MARK: - LifeCycle + override func viewDidLoad() { + super.viewDidLoad() + setupUI() + } + +} +// MARK: - UI +extension LoginViewController { + private func setupUI() { + setupTableView() + } + + private func setupTableView() { + modelDataSource = LoginDataSource() + modelController = LoginModelController(delegate: self, viewController: self) + + modelDataSource?.outputProtocol = modelController + modelController?.inputProtocol = modelDataSource + + tableView.delegate = modelDataSource + tableView.dataSource = modelDataSource + + tableView.keyboardDismissMode = .interactive + tableView.set(cells: [FieldTableViewCell.self]) + tableView.isScrollEnabled = false + tableView.reloadData() + } + +} + +// MARK: - LoginViewControllerDelegate +extension LoginViewController: LoginViewControllerDelegate { + func updateUI() { + tableView.beginUpdates() + tableView.endUpdates() + } +} diff --git a/TraccarClient/LoginViewController/Model/LoginDataProvider.swift b/TraccarClient/LoginViewController/Model/LoginDataProvider.swift new file mode 100644 index 0000000000000000000000000000000000000000..b963f64854c4608b0f34196b5701fb81fda29a97 --- /dev/null +++ b/TraccarClient/LoginViewController/Model/LoginDataProvider.swift @@ -0,0 +1,38 @@ +// +// LoginDataProvider.swift +// TraccarClient +// +// Created by George Makhoul on 26/10/2023. +// Copyright © 2023 Traccar. All rights reserved. +// + +import Foundation +import UIKit + +final class LoginDataProvider { + // MARK: - Properties + private var fields: [KNField] = [] + + // MARK: - Methods + func signinData() -> [KNField] { + let email = KNField { field in + field.field = .username + field.title = "Username" + field.isRequired = true + field.type = .text + } + + let password = KNField { field in + field.field = .password + field.title = "Password" + field.isRequired = true + field.type = .text + } + + fields = [ + email, + password, + ] + return fields + } +} diff --git a/TraccarClient/LoginViewController/Model/LoginDataSource.swift b/TraccarClient/LoginViewController/Model/LoginDataSource.swift new file mode 100644 index 0000000000000000000000000000000000000000..e043b12cc18dc16af8d97b7097682dda3bd5de2f --- /dev/null +++ b/TraccarClient/LoginViewController/Model/LoginDataSource.swift @@ -0,0 +1,65 @@ +// +// LoginDataSource.swift +// TraccarClient +// +// Created by George Makhoul on 26/10/2023. +// Copyright © 2023 Traccar. All rights reserved. +// + +import UIKit +import Foundation + +final class LoginDataSource: NSObject { + + // MARK: - Properties + private var fields: [KNField] = [] + weak var outputProtocol: LoginOutputProtocol? + + // MARK: - Init + override init() { + // + } +} + +// MARK: - TableView +extension LoginDataSource: UITableViewDelegate, UITableViewDataSource { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + fields.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let field = fields[indexPath.row] + + if field.type == .text { + let cell = tableView.dequeue(withCell: FieldTableViewCell.self) + cell.delegate = self + + cell.set(field: field, indexPath: indexPath) + return cell + } + + return UITableViewCell() + } + + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return fields[indexPath.row].height + } +} + + +// MARK: - Input Protocol +extension LoginDataSource: LoginInputProtocol { + func setFields(fields: [KNField]) { + self.fields = fields + + outputProtocol?.reloadUI() + } +} + +// MARK: - Field Protocok +extension LoginDataSource: KNTextFieldViewDelegate { + func updateUI(for field: KNField?) { + outputProtocol?.reloadUI() + } +} + diff --git a/TraccarClient/LoginViewController/Model/LoginModelController.swift b/TraccarClient/LoginViewController/Model/LoginModelController.swift new file mode 100644 index 0000000000000000000000000000000000000000..91f99e6395476d50715cc865fc2e4bc2028a4607 --- /dev/null +++ b/TraccarClient/LoginViewController/Model/LoginModelController.swift @@ -0,0 +1,46 @@ +// +// LoginModelController.swift +// TraccarClient +// +// Created by George Makhoul on 26/10/2023. +// Copyright © 2023 Traccar. All rights reserved. +// + +import Foundation +import UIKit + +final class LoginModelController { + // MARK: - Properties + var fields: [KNField] = [] + var viewController: UIViewController + private weak var delegate: LoginViewControllerDelegate? + weak var window: UIWindow? + + weak var inputProtocol: LoginInputProtocol? { + didSet { + setupData() + } + } + + // MARK: - Init + init(delegate: LoginViewControllerDelegate?, viewController: UIViewController) { + self.delegate = delegate + self.viewController = viewController + } + + private func setupData() { + let dataProvider = LoginDataProvider() + fields = dataProvider.signinData() + + inputProtocol?.setFields(fields: fields) + } +} + +// MARK: - Output Protocol +extension LoginModelController: LoginOutputProtocol { + + func reloadUI() { + delegate?.updateUI() + } +} + diff --git a/TraccarClient/LoginViewController/Model/LoginViewControllerProtocol.swift b/TraccarClient/LoginViewController/Model/LoginViewControllerProtocol.swift new file mode 100644 index 0000000000000000000000000000000000000000..d88270b1a235436092c2e53abc5dbc9b3accd1a5 --- /dev/null +++ b/TraccarClient/LoginViewController/Model/LoginViewControllerProtocol.swift @@ -0,0 +1,23 @@ +// +// LoginViewControllerProtocol.swift +// TraccarClient +// +// Created by George Makhoul on 26/10/2023. +// Copyright © 2023 Traccar. All rights reserved. +// + +import UIKit +import Foundation + +protocol LoginViewControllerDelegate: AnyObject { + func updateUI() + +} + +protocol LoginInputProtocol: AnyObject { + func setFields(fields: [KNField]) +} + +protocol LoginOutputProtocol: AnyObject { + func reloadUI() +} diff --git a/TraccarClient/LoginViewController.xib b/TraccarClient/LoginViewController/View/LoginViewController.xib similarity index 80% rename from TraccarClient/LoginViewController.xib rename to TraccarClient/LoginViewController/View/LoginViewController.xib index 00485dc670700e704dfd8239a7a826be7a12cc3c..df509156c5949ee86121c7eed68324f7089da194 100644 --- a/TraccarClient/LoginViewController.xib +++ b/TraccarClient/LoginViewController/View/LoginViewController.xib @@ -19,6 +19,7 @@ <objects> <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="LoginViewController" customModule="TraccarClient" customModuleProvider="target"> <connections> + <outlet property="tableView" destination="cqa-qG-jss" id="WXO-8H-fjI"/> <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/> </connections> </placeholder> @@ -46,14 +47,22 @@ <nil key="textColor"/> <nil key="highlightedColor"/> </label> + <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="-1" estimatedSectionHeaderHeight="-1" sectionFooterHeight="-1" estimatedSectionFooterHeight="-1" translatesAutoresizingMaskIntoConstraints="NO" id="cqa-qG-jss"> + <rect key="frame" x="32" y="313.66666666666674" width="329" height="472.33333333333326"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> + </tableView> </subviews> <viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/> <color key="backgroundColor" systemColor="systemBackgroundColor"/> <constraints> + <constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="cqa-qG-jss" secondAttribute="trailing" constant="32" id="3jQ-sI-aAm"/> <constraint firstItem="rPb-N8-5pB" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="CJs-Qh-u3u"/> + <constraint firstItem="fnl-2z-Ty3" firstAttribute="bottom" secondItem="cqa-qG-jss" secondAttribute="bottom" constant="32" id="Dqf-I3-asf"/> <constraint firstItem="rPb-N8-5pB" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="75" id="HjK-k3-B52"/> + <constraint firstItem="cqa-qG-jss" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="32" id="bDg-CD-ZNz"/> <constraint firstItem="ejG-GP-Evp" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="nuW-Lh-yVC"/> <constraint firstItem="ejG-GP-Evp" firstAttribute="top" secondItem="jC6-Ly-QKC" secondAttribute="bottom" constant="7" id="o0G-Yj-sgP"/> + <constraint firstItem="cqa-qG-jss" firstAttribute="top" secondItem="ejG-GP-Evp" secondAttribute="bottom" constant="25" id="uqb-3w-Sf4"/> <constraint firstItem="jC6-Ly-QKC" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="x2w-Bh-kGc"/> <constraint firstItem="jC6-Ly-QKC" firstAttribute="top" secondItem="rPb-N8-5pB" secondAttribute="bottom" constant="10" id="yvR-wY-vOb"/> </constraints> diff --git a/TraccarClient/TraccarClient-Info.plist b/TraccarClient/TraccarClient-Info.plist index b07535fbfe47b6286e64d311cc5511ae6ea555aa..dad50640b1bb1c0a127d5b7883883ef43be07559 100644 --- a/TraccarClient/TraccarClient-Info.plist +++ b/TraccarClient/TraccarClient-Info.plist @@ -35,6 +35,27 @@ <string>This is a tracking application and therefore requires access to location services</string> <key>NSLocationWhenInUseUsageDescription</key> <string>This is a tracking application and therefore requires access to location services</string> + <key>UIAppFonts</key> + <array> + <string>Montserrat-Black.ttf</string> + <string>Montserrat-BlackItalic.ttf</string> + <string>Montserrat-Bold.ttf</string> + <string>Montserrat-BoldItalic.ttf</string> + <string>Montserrat-ExtraBold.ttf</string> + <string>Montserrat-ExtraBoldItalic.ttf</string> + <string>Montserrat-ExtraLight.ttf</string> + <string>Montserrat-ExtraLightItalic.ttf</string> + <string>Montserrat-Italic.ttf</string> + <string>Montserrat-Light.ttf</string> + <string>Montserrat-LightItalic.ttf</string> + <string>Montserrat-Medium.ttf</string> + <string>Montserrat-MediumItalic.ttf</string> + <string>Montserrat-Regular.ttf</string> + <string>Montserrat-SemiBold.ttf</string> + <string>Montserrat-SemiBoldItalic.ttf</string> + <string>Montserrat-Thin.ttf</string> + <string>Montserrat-ThinItalic.ttf</string> + </array> <key>UIApplicationShortcutItems</key> <array> <dict> @@ -85,28 +106,9 @@ <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> </array> + <key>UIUserInterfaceStyle</key> + <string>Light</string> <key>UIViewControllerBasedStatusBarAppearance</key> <false/> - <key>UIAppFonts</key> - <array> - <string>Montserrat-Black.ttf</string> - <string>Montserrat-BlackItalic.ttf</string> - <string>Montserrat-Bold.ttf</string> - <string>Montserrat-BoldItalic.ttf</string> - <string>Montserrat-ExtraBold.ttf</string> - <string>Montserrat-ExtraBoldItalic.ttf</string> - <string>Montserrat-ExtraLight.ttf</string> - <string>Montserrat-ExtraLightItalic.ttf</string> - <string>Montserrat-Italic.ttf</string> - <string>Montserrat-Light.ttf</string> - <string>Montserrat-LightItalic.ttf</string> - <string>Montserrat-Medium.ttf</string> - <string>Montserrat-MediumItalic.ttf</string> - <string>Montserrat-Regular.ttf</string> - <string>Montserrat-SemiBold.ttf</string> - <string>Montserrat-SemiBoldItalic.ttf</string> - <string>Montserrat-Thin.ttf</string> - <string>Montserrat-ThinItalic.ttf</string> - </array> </dict> </plist> diff --git a/TraccarClient/UITableView.swift b/TraccarClient/UITableView.swift new file mode 100644 index 0000000000000000000000000000000000000000..b3ccd8a9454fabbdc17a138aa07bcecfa3cb003e --- /dev/null +++ b/TraccarClient/UITableView.swift @@ -0,0 +1,99 @@ +// +// UITableView.swift +// TraccarClient +// +// Created by George Makhoul on 26/10/2023. +// Copyright © 2023 Traccar. All rights reserved. +// + +import UIKit + +extension UITableView { + + var automatic: CGFloat { + UITableView.automaticDimension + } + + // MARK: - Set Cell & Setup Table + func set(cell: UITableViewCell.Type) { + tableFooterView = UIView() + tableHeaderView = UIView() + separatorStyle = .none + backgroundColor = .clear + + register(cell: cell) + } + + func set(cells: [UITableViewCell.Type]) { + tableFooterView = UIView() + tableHeaderView = UIView() + separatorStyle = .none + backgroundColor = .clear + + register(cells: cells) + } + + // MARK: - Register Cell + func register(cell: UITableViewCell.Type) { + let nib = UINib(nibName: cell.name, bundle: nil) + register(nib, forCellReuseIdentifier: cell.name) + } + + func register(cells: [UITableViewCell.Type]) { + cells.forEach { + let nib = UINib(nibName: $0.name, bundle: nil) + register(nib, forCellReuseIdentifier: $0.name) + } + } + + func register(header: UITableViewHeaderFooterView.Type) { + let nib = UINib(nibName: header.name, bundle: nil) + register(nib, forHeaderFooterViewReuseIdentifier: header.name) + } + + func register(headers: [UITableViewHeaderFooterView.Type]) { + headers.forEach { + let nib = UINib(nibName: $0.name, bundle: nil) + register(nib, forHeaderFooterViewReuseIdentifier: $0.name) + } + } + + // MARK: - Dequeue Cell + func dequeue<CellType: UITableViewCell>(withCell cell: CellType.Type, at indexPath: IndexPath) -> CellType { + dequeueReusableCell(withIdentifier: cell.name, for: indexPath) as! CellType + } + + func dequeue<CellType: UITableViewCell>(withCell cell: CellType.Type) -> CellType { + dequeueReusableCell(withIdentifier: cell.name) as! CellType + } + + func dequeue<HeaderType: UITableViewHeaderFooterView>(withHeader header: HeaderType.Type, at section: Int) -> HeaderType { + dequeueReusableHeaderFooterView(withIdentifier: header.name) as! HeaderType + } + + // table's content view + var contentHeight: CGFloat { + var height: CGFloat = 0 + + for section in 0..<numberOfSections { + height += rectForHeader(inSection: section).height + + let rows = numberOfRows(inSection: section) + for row in 0..<rows { + height += rectForRow(at: IndexPath(row: row, section: section)).height + } + } + + return height + } + + func prefetchSpinner() { + let spinner = UIActivityIndicatorView(style: .medium) + spinner.color = .purple + spinner.startAnimating() + spinner.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: bounds.width, height: CGFloat(44)) + tableFooterView = spinner + tableFooterView?.isHidden = false + } +} +