diff --git a/OpenSourceController/Classes/Controller/OpenSourceController.swift b/OpenSourceController/Classes/Controller/OpenSourceController.swift new file mode 100644 index 0000000..efcb9cf --- /dev/null +++ b/OpenSourceController/Classes/Controller/OpenSourceController.swift @@ -0,0 +1,32 @@ +// +// OpenSourceController.swift +// Pods +// +// Created by Florian Gabach on 05/02/2017. +// +// + +import UIKit + +public class OpenSourceController: NSObject { + + // Contains list of licence object + public var licences: [LicenceFile]? + + /// Present OpenSourceViewController embbeded in navigation controller + /// + /// - Parameter from: the source controller + public final func presentOpenSourceController(from: UIViewController) { + // Create open source controller + let licenceController = OpenSourceViewController() + + // Init licence + licenceController.licences = self.licences + + // Embed in navigation controller + let navController = UINavigationController(rootViewController: licenceController) + + // Present controller + from.present(navController, animated: true) + } +} diff --git a/OpenSourceController/Classes/Controller/OpenSourceViewController.swift b/OpenSourceController/Classes/Controller/OpenSourceViewController.swift new file mode 100644 index 0000000..53f8e4b --- /dev/null +++ b/OpenSourceController/Classes/Controller/OpenSourceViewController.swift @@ -0,0 +1,158 @@ +// +// OpenSourceViewController.swift +// Pods +// +// Created by Florian Gabach on 05/02/2017. +// +// + +import UIKit + +class OpenSourceViewController: UITableViewController { + + // MARK: - Var + + /// Loading indicator + fileprivate var indicator = UIActivityIndicatorView() + + /// TableViewCell identifier + private let reuseIdentifier = "openSourceCell" + + /// Contains all licence object before downloaded + var licences: [LicenceFile]? + + /// Contains all licences object after downloaded + fileprivate var downloadedLicence: [LicenceFile]? { + didSet { + // Update UI + DispatchQueue.main.async { + self.stopLoading() + self.tableView.reloadData() + } + } + } + + // MARK: - Lifecyle + + override func viewDidLoad() { + super.viewDidLoad() + + // Prepare tableview + self.prepareTableView() + + // Download licences + self.prepareLicences() + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + } + + // MARK: - Prepare + + /// Download licences + fileprivate func prepareLicences() { + if let licences = self.licences { + self.startLoading() + LicenceDownloader.downloadLicences(licences: licences) { () in + // Update licences + self.downloadedLicence = self.licences + } + } + } + + /// Init tableView dataSource, delegate, bar button & title + fileprivate func prepareTableView() { + // Common init + self.tableView.tableFooterView = UIView() + self.title = NSLocalizedString("Tiers library", comment: "") + self.tableView.register(OpenSourceTableViewCell.self, forCellReuseIdentifier: self.reuseIdentifier) + self.tableView.dataSource = self + self.tableView.delegate = self + self.tableView.separatorStyle = .singleLine + + // Close button (on the right corner of navigation bar) + let closeButton = UIBarButtonItem(barButtonSystemItem: .stop, + target: self, + action: #selector(self.closePicker)) + self.navigationItem.rightBarButtonItem = closeButton + + // Loading indicator + self.prepareActivityIndicator() + } + + // MARK: - Loading indicator + + /// Prepare UIActivityIndicatorView and display it at the center of the view + fileprivate func prepareActivityIndicator() { + self.indicator = UIActivityIndicatorView(frame:CGRect(x: 0, y: 0, width: 40, height: 40) ) + self.indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray + self.indicator.center = self.view.center + self.view.addSubview(indicator) + } + + /// Start loading : start the loader animation + fileprivate func startLoading() { + self.indicator.startAnimating() + self.indicator.backgroundColor = UIColor.clear + self.indicator.color = UIColor.black + self.indicator.isHidden = false + } + + /// Stop loading : stop and hide the loader + fileprivate func stopLoading() { + self.indicator.hidesWhenStopped = true + self.indicator.stopAnimating() + self.indicator.isHidden = true + } + + // MARK: - Table View Data Source + + override func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return self.downloadedLicence?.count ?? 0 + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + var cell = tableView.dequeueReusableCell(withIdentifier: self.reuseIdentifier, + for: indexPath) as? OpenSourceTableViewCell + if cell == nil { + cell = OpenSourceTableViewCell(style: UITableViewCellStyle.default, + reuseIdentifier: self.reuseIdentifier) + } + + let libraryTitleAttribut = [NSFontAttributeName: UIFont.boldSystemFont(ofSize: UIFont.systemFontSize + 2)] + let libraryLicenceAttribut = [NSFontAttributeName: UIFont.systemFont(ofSize: UIFont.systemFontSize)] + let libraryTitle = NSMutableAttributedString(string: self.downloadedLicence?[indexPath.row].title ?? "", + attributes: libraryTitleAttribut) + libraryTitle.append(NSAttributedString(string: "\n\n")) + libraryTitle.append(NSAttributedString(string: self.downloadedLicence?[indexPath.row].detail ?? "", + attributes: libraryLicenceAttribut)) + cell?.textLabel?.attributedText = libraryTitle + + return cell! + } + + override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { + return UITableViewAutomaticDimension + } + + // MARK: - Action + + /// Handler for click on close button + @objc fileprivate func closePicker() { + self.dismissController() + } + + // MARK: - Navigation + + /// Dismiss the OpenSourceController + func dismissController() { + DispatchQueue.main.async { + self.dismiss(animated: true, completion: nil) + } + } +} diff --git a/OpenSourceController/Classes/Model/LicenceDownloader.swift b/OpenSourceController/Classes/Model/LicenceDownloader.swift new file mode 100644 index 0000000..faf8264 --- /dev/null +++ b/OpenSourceController/Classes/Model/LicenceDownloader.swift @@ -0,0 +1,38 @@ +// +// LicenceDownloader.swift +// Pods +// +// Created by Florian Gabach on 21/02/2017. +// +// + +import UIKit + +class LicenceDownloader: NSObject { + + /// Download every licence + /// + /// - Parameters: + /// - licences: array which contains licence model model + /// - completion: end downloading completion + class func downloadLicences(licences: [LicenceFile], + completion: @escaping () -> Void) { + // Number of licences + let licenceCount = licences.count + + // Already licence downloaded + var alreadyDownloaded = 0 + + // Download licence's detail for every lience + for licence in licences { + licence.downloadLicenceDetail(completion: { () in + alreadyDownloaded += 1 + + // If this is the last licence, perfom completion + if licenceCount == alreadyDownloaded { + completion() + } + }) + } + } +} diff --git a/OpenSourceController/Classes/Model/LicenceFile.swift b/OpenSourceController/Classes/Model/LicenceFile.swift new file mode 100644 index 0000000..d77567f --- /dev/null +++ b/OpenSourceController/Classes/Model/LicenceFile.swift @@ -0,0 +1,56 @@ +// +// LicenceFile.swift +// Pods +// +// Created by Florian Gabach on 05/02/2017. +// +// + +import UIKit + +public class LicenceFile: NSObject { + + // MARK- Var + + /// Name of the library + var title: String? + + /// Url of the library's licence + var url: String + + /// Library's licence + var detail: String? + + // MARK- Init + + /// Licence initializer + /// + /// - Parameters: + /// - title: name of the library + /// - url: url of the licence content + public init(title: String, url: String) { + self.title = title + self.url = url + } + + /// Download licence detail + /// + /// - Parameter completion: end of download handler + func downloadLicenceDetail(completion: @escaping (Void) -> Void) { + if let url = URL(string: self.url) { + let task = URLSession.shared.dataTask(with: url) { (data, _, _) in + if let data = data, + let html = String(data: data, encoding: String.Encoding.utf8) { + + // Update licence model + self.detail = html + + // Log + print("Licence for \(self.title ?? "") downloaded with success.") + } + completion() + } + task.resume() + } + } +} diff --git a/OpenSourceController/Classes/View/OpenSourceTableViewCell.swift b/OpenSourceController/Classes/View/OpenSourceTableViewCell.swift new file mode 100644 index 0000000..cd6cc7a --- /dev/null +++ b/OpenSourceController/Classes/View/OpenSourceTableViewCell.swift @@ -0,0 +1,63 @@ +// +// OpenSourceTableViewCell.swift +// Pods +// +// Created by Florian Gabach on 05/02/2017. +// +// + +import UIKit + +class OpenSourceTableViewCell: UITableViewCell { + + // MARK: IBOutlet + + @IBOutlet var licenceTitle: UILabel! + @IBOutlet var licenceDesc: UILabel! + + // MARK: - Lifecycle + + override init(style: UITableViewCellStyle, reuseIdentifier: String?) { + super.init(style: .default, + reuseIdentifier: reuseIdentifier) + + self.prepareCellComponent() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + } + + override func layoutSubviews() { + super.layoutSubviews() + } + + // MARK: - Prepare + + func prepareCellComponent() { + // Text + self.textLabel?.numberOfLines = 0 + + // Common init + self.accessoryType = .none + self.selectionStyle = .none + } + + // MARK: - Configure + + /// Initialize the cell content with Licence model + /// + /// - Parameter licence: the licence model + func configure(licence: LicenceFile) { + + // Library's name + self.licenceTitle.text = licence.title + + // Library licence's detail + self.licenceDesc.text = licence.detail + } +}