- Added the network library with proper versioning

- Made the network adapter
- Made the config file to hold the url auth
This commit is contained in:
2024-05-07 11:12:59 +05:30
parent 32f9ddaa7d
commit 3de76138fc
15 changed files with 604 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
//
// FontCusto.swift
// WOKA
//
// Created by MacBook Pro on 06/05/24.
//
import Foundation

View File

@@ -0,0 +1,8 @@
//
// UserDataDM.swift
// WOKA
//
// Created by MacBook Pro on 06/05/24.
//
import Foundation

9
WOKA/Config.xcconfig Normal file
View File

@@ -0,0 +1,9 @@
//
// Config.xcconfig
// WOKA
//
// Created by MacBook Pro on 06/05/24.
//
// Configuration settings file format documentation can be found at:
// https://help.apple.com/xcode/#/dev745c5c974

View File

@@ -0,0 +1,23 @@
//
// File.swift
// WOKA
//
// Created by MacBook Pro on 06/05/24.
//
import Foundation
extension K{
struct ConstantString{
static let dollar = "$"
static let passRequirement = "- Be at least 8 characters in length. \n- Contain both upper and lowercase alphabetic characters (e.g. A-Z, a-z). \n- Have at least one numerical character (e.g. 0-9). \n- Have at least one special character (e.g. ~!@#$%^&*()_-+=)."
static let unRecognised = "Unreccognised error"
static let noInternet = "Make sure you are connected to the internet!"
static let minAge = "Minimum age requirement is 18 or above"
}
}

View File

@@ -0,0 +1,8 @@
//
// ExtensionVCToastAlert.swift
// WOKA
//
// Created by MacBook Pro on 06/05/24.
//
import Foundation

View File

@@ -0,0 +1,55 @@
//
// File.swift
// WOKA
//
// Created by MacBook Pro on 06/05/24.
//
import UIKit
open class LLSpinner {
internal static var spinnerView: UIActivityIndicatorView?
public static var style: UIActivityIndicatorView.Style = .large
public static var backgroundColor: UIColor = UIColor(white: 0, alpha: 0.6)
internal static var touchHandler: (() -> Void)?
public static func spin(style: UIActivityIndicatorView.Style = style, backgroundColor: UIColor = backgroundColor, touchHandler: (() -> Void)? = nil) {
if spinnerView == nil,
let window = UIApplication.shared.mainKeyWindow {
let frame = UIScreen.main.bounds
spinnerView = UIActivityIndicatorView(frame: frame)
spinnerView?.center = CGPoint(x: window.frame.size.width / 2,
y: window.frame.size.height / 2)
spinnerView!.backgroundColor = backgroundColor
spinnerView!.style = style
spinnerView!.color = .white
window.addSubview(spinnerView!)
spinnerView!.startAnimating()
}
if touchHandler != nil {
self.touchHandler = touchHandler
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(runTouchHandler))
spinnerView!.addGestureRecognizer(tapGestureRecognizer)
}
}
@objc internal static func runTouchHandler() {
if touchHandler != nil {
touchHandler!()
}
}
public static func stop() {
if let _ = spinnerView {
spinnerView!.stopAnimating()
spinnerView!.removeFromSuperview()
spinnerView = nil
}
}
}

View File

@@ -0,0 +1,8 @@
//
// Toast.swift
// WOKA
//
// Created by MacBook Pro on 06/05/24.
//
import Foundation

View File

@@ -0,0 +1,108 @@
//
// File.swift
// WOKA
//
// Created by MacBook Pro on 06/05/24.
//
import UIKit
class Utilities{
let activityIndicator = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.medium)
// static func setupProgressHUD() {
// let loaderColor = UIColor.green
// let backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
//
// SVProgressHUD.setInfoImage(UIImage(named: "AppLogo")!)
// SVProgressHUD.setBackgroundColor(backgroundColor)
// SVProgressHUD.setForegroundColor(loaderColor)
// // don't let user press anything on screen while SVProgessHUD is active
// SVProgressHUD.setDefaultMaskType(.black)
// }
static func startProgressHUD(progress: Float? = nil) {
LLSpinner.spin()
// if let progress = progress {
// SVProgressHUD.showProgress(progress)
// } else {
// SVProgressHUD.show()
// }
}
static func dismissProgressHUD() {
DispatchQueue.main.async {
LLSpinner.stop()
}
}
static func stopActivity(view : UIView){
Utilities().activityIndicator.stopAnimating()
}
static func alertWithBtn(title : String , msgBody : String, okBtnStr : String?,vc : UIViewController){
let alert = UIAlertController(title: title, message: msgBody, preferredStyle: .alert)
let titleAttrString = NSMutableAttributedString(string: title != "" ? (title + "\n") : "", attributes: [NSAttributedString.Key.font: UIFont(name: "Nunito-Medium", size: 20)! as Any])
alert.setValue(titleAttrString, forKey: "attributedTitle")
var messageMutableString = NSMutableAttributedString()
messageMutableString = NSMutableAttributedString(string: msgBody as String, attributes: [NSAttributedString.Key.font:UIFont(name: "Nunito-Regular", size: 18)!])
messageMutableString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.black, range: NSRange(location:0,length:msgBody.count))
alert.setValue(messageMutableString, forKey: "attributedMessage")
let okAction = UIAlertAction(title: okBtnStr ?? "OK", style: .default, handler: nil)
okAction.setValue(UIColor.appColor(.AppBaseBlueColor), forKey: "titleTextColor")
alert.addAction(okAction)
vc.present(alert, animated: true, completion: nil)
}
static func alertWithBtnCompletion(title : String , msgBody : String, okBtnStr : String?,vc : UIViewController ,onCompletion : @escaping (Bool) -> Void){
let alert = UIAlertController(title: title, message: nil, preferredStyle: .alert)
let okAction = UIAlertAction(title: okBtnStr ?? "OK", style: .default, handler: {_ in
onCompletion(true)
})
let messageAttributes = [NSAttributedString.Key.font: UIFont(name: "Nunito-Regular", size: 18)!, NSAttributedString.Key.foregroundColor: UIColor.black]
let messageString = NSAttributedString(string: msgBody, attributes: messageAttributes)
okAction.setValue(UIColor.appColor(.AppBaseBlueColor), forKey: "titleTextColor")
alert.addAction(okAction)
alert.setValue(messageString, forKey: "attributedMessage")
vc.present(alert, animated: true, completion: nil)
}
static func reportBug(message: String, line: Int = #line, file: String = #file) {
print("Line: \(line): File \(file): \(message)")
//TODO: Send report to ferofly
}
static func alert(line: Int = #line, file: String = #file, title: String, message: String, viewController: UIViewController, toastTime: TimeInterval = 0, onCompletion: (() -> Void)? = nil) {
print("Line: \(line): File \(file): \(title): \(message)")
let alertVC = UIAlertController(title: title, message: message, preferredStyle: .alert)
if toastTime == 0 {
let action = UIAlertAction(title: "Ok", style: .default) { (action) in
alertVC.dismiss(animated: true, completion: onCompletion)
}
alertVC.addAction(action)
}
DispatchQueue.main.async {
viewController.present(alertVC, animated: true, completion: nil)
if toastTime > 0 {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + toastTime) {
alertVC.dismiss(animated: true, completion: onCompletion)
}
}
}
}
}

View File

@@ -0,0 +1,22 @@
//
// File.swift
// WOKA
//
// Created by MacBook Pro on 06/05/24.
//
import UIKit
extension UIApplication {
var mainKeyWindow: UIWindow? {
get {
if #available(iOS 13, *) {
return connectedScenes
.flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
.first { $0.isKeyWindow }
} else {
return keyWindow
}
}
}
}

View File

@@ -0,0 +1,8 @@
//
// APIEndPoints.swift
// WOKA
//
// Created by MacBook Pro on 06/05/24.
//
import Foundation

View File

@@ -0,0 +1,8 @@
//
// BaseResponseModel.swift
// WOKA
//
// Created by MacBook Pro on 06/05/24.
//
import Foundation

View File

@@ -0,0 +1,173 @@
//
// NetworkManager.swift
// WOKA
//
// Created by MacBook Pro on 06/05/24.
//
import Alamofire
class NetworkManager{
static let shareInstance = NetworkManager()
private init() {}
enum APIError: Error {
case networkError
case noNetwork(message:String)
case invalidURL
case parameterEncodingFailed
case responseValidationFailed
case unknown(message: String)
case custom(message: String)
}
/// This function will do the network call for HTTPMethod & Encoding is URLEncoding with contentType ["application/json"]
///
///
/// - Warning: The returned string is not localized.
///
/// Usage:
///
/// Alamofire network call Generic (.get , .post, .put.).
///
/// - Parameter (header : HTTPHeaders , Params :[String : Any] , URL , Dedocable Generic T Struct. , queue : dispatchQueue decide)
/// - NOTE Oncompletion will be called on main thread so no need to specify the main thread for UI updates
/// - Returns: This function returns a GENERIC response base on the T Model & APIError .
func apiRequest<T: Codable>(
url: URLConvertible,
method: HTTPMethod,
parameters: Parameters? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil,
queue: DispatchQueue = QueueHelper.background,
completionHandler: @escaping (Result<T, APIError>) -> Void
) {
// Stop monitoring network reachability
NetworkReachibility.shared.stopMonitoring()
// Execute the request on the specified queue
queue.async {
AF.request(url, method: method, parameters: parameters, encoding: encoding, headers: headers, requestModifier: { $0.timeoutInterval = 30 })
.validate(statusCode: 200..<300)
.responseDecodable(of: T.self) { response in
switch response.result {
case .success(let value):
// Handle successful response on the main thread
DispatchQueue.main.async {
completionHandler(.success(value))
}
case .failure(let error):
// Handle failure cases
if let afError = error as? AFError {
switch afError {
case .sessionTaskFailed(let urlError):
if urlError._code == -1020 || urlError._code == -1009 {
// Handle network error on the main thread
DispatchQueue.main.async {
completionHandler(.failure(.noNetwork(message: K.ConstantString.noInternet)))
}
} else {
// Handle other network errors on the main thread
DispatchQueue.main.async {
completionHandler(.failure(.networkError))
}
}
case .invalidURL:
// Handle invalid URL error on the main thread
DispatchQueue.main.async {
completionHandler(.failure(.invalidURL))
}
case .parameterEncodingFailed:
// Handle parameter encoding failure on the main thread
DispatchQueue.main.async {
completionHandler(.failure(.parameterEncodingFailed))
}
case .responseValidationFailed:
// Handle response validation failure on the main thread
DispatchQueue.main.async {
completionHandler(.failure(.responseValidationFailed))
}
default:
// Handle other network errors on the main thread
DispatchQueue.main.async {
completionHandler(.failure(.networkError))
}
}
} else {
// Handle unrecognized errors on the main thread
DispatchQueue.main.async {
completionHandler(.failure(.unknown(message: K.ConstantString.unRecognised)))
}
}
}
}
}
}
}
// func handleAFError(error: Error)-> Int? {
// if let afError = error as? AFError {
// // This error is of type AFError, and you can access its properties.
// let errorCode = afError.responseCode
// return errorCode
// } else {
// // Handle other types of errors or unsupported cases
// return nil
// }
// }
//
// func uploadFormData<T: Codable>(
// url: URLConvertible,
// method: HTTPMethod,
// headers: HTTPHeaders? = nil,
// params : [String : Any]?,
// image : UIImage?,
// formData: [MultipartFormData],
// completionHandler: @escaping (Result<T, AFError>) -> Void
// ) {
//
// let imageData = image?.jpegData(compressionQuality: 0.4)!
// let imageKey = "contact_photo" // Change me
// AF.upload(multipartFormData: { multiPart in
// for (key, value) in (params ?? [:]) {
// if let arrayObj = value as? [Any] {
// for index in 0..<arrayObj.count {
// if key != "contact_photo"{
// multiPart.append("\(arrayObj[index])".data(using: .utf8)!, withName: "\(key)[\(index)]")
// }
// }
// } else {
// if key != "contact_photo"{
// multiPart.append("\(value)".data(using: .utf8)!, withName: key)
// }
// }
// }
// if let imageData{
// multiPart.append(imageData, withName: imageKey, fileName: "file.jpg", mimeType: "image/jpg")
// }
// }, to: url, headers: headers).responseDecodable { (response: DataResponse<T,AFError>) in
// switch response.result {
// case .success(let value):
// completionHandler(.success(value))
// case .failure(let error):
// if let statusCode = response.response?.statusCode {
// switch statusCode {
// case 400..<500:
// // Handle client-side errors (4xx)
// completionHandler(.failure(.custom(message: "Client-side error: \(statusCode)")))
// case 500..<600:
// // Handle server-side errors (5xx)
// completionHandler(.failure(.custom(message: "Server-side error: \(statusCode)")))
// default:
// completionHandler(.failure(.unknown))
// }
// } else {
// completionHandler(.failure(.unknown))
// }
// }
// }
// }
//}

View File

@@ -0,0 +1,43 @@
//
// NetworkReachibility.swift
// WOKA
//
// Created by MacBook Pro on 06/05/24.
//
import Alamofire
class NetworkReachibility{
static let shared = NetworkReachibility()
private init(){}
let manager = NetworkReachabilityManager(host: "www.apple.com")
fileprivate var isInternetReachable = false
func startMonitoring(onCompletion : @escaping (Bool) -> Void) {
manager?.startListening(onQueue: DispatchQueue.main, onUpdatePerforming: { (status) in
switch status {
case .notReachable:
print("network connection status - lost")
self.isInternetReachable = false
onCompletion(false)
case .reachable(.ethernetOrWiFi):
print("network connection status - ethernet/WiFI")
self.isInternetReachable = true
onCompletion(true)
case .reachable(.cellular):
print("network connection status - cellular")
self.isInternetReachable = true
onCompletion(true)
default:
self.isInternetReachable = false
onCompletion(false)
break
}
})
}
func stopMonitoring(){
manager?.stopListening()
}
}

View File

@@ -0,0 +1,25 @@
//
// File.swift
// WOKA
//
// Created by MacBook Pro on 06/05/24.
//
import Foundation
/*
this are the predefined queuehelper
modify as required
*/
class QueueHelper {
static let queue = DispatchQueue(label: "com.simpliTend")
static let queueHome = DispatchQueue(label: "com.simpliTend.home")
static let group = DispatchGroup()
static let group2 = DispatchGroup()
static let group3 = DispatchGroup()
static let background = DispatchQueue.global(qos: .background)
static let utilityGroup = DispatchQueue.global(qos: .utility)
static let userInteractive = DispatchQueue.global(qos: .userInteractive)
static let semaphore = DispatchSemaphore(value: 1)
}

View File

@@ -0,0 +1,98 @@
//
// File.swift
// WOKA
//
// Created by MacBook Pro on 06/05/24.
//
import Foundation
enum ValueWrapper: Codable {
case stringValue(String)
case intValue(Int)
case doubleValue(Double)
case boolValue(Bool)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let value = try? container.decode(String.self) {
self = .stringValue(value)
return
}
if let value = try? container.decode(Bool.self) {
self = .boolValue(value)
return
}
if let value = try? container.decode(Double.self) {
self = .doubleValue(value)
return
}
if let value = try? container.decode(Int.self) {
self = .intValue(value)
return
}
throw DecodingError.typeMismatch(ValueWrapper.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for ValueWrapper"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case let .stringValue(value):
try container.encode(value)
case let .boolValue(value):
try container.encode(value)
case let .intValue(value):
try container.encode(value)
case let .doubleValue(value):
try container.encode(value)
}
}
var rawValue: String {
var result: String
switch self {
case let .stringValue(value):
result = value
case let .boolValue(value):
result = String(value)
case let .intValue(value):
result = String(value)
case let .doubleValue(value):
result = String(value)
}
return result
}
var intValue: Int? {
var result: Int?
switch self {
case let .stringValue(value):
result = Int(value)
case let .intValue(value):
result = value
case let .boolValue(value):
result = value ? 1 : 0
case let .doubleValue(value):
result = Int(value)
}
return result
}
var boolValue: Bool? {
var result: Bool?
switch self {
case let .stringValue(value):
result = Bool(value)
case let .boolValue(value):
result = value
case let .intValue(value):
result = Bool(truncating: value as NSNumber)
case let .doubleValue(value):
result = Bool(truncating: value as NSNumber)
}
return result
}
}