From 1b292bc251b3dbef532dacad9705bd197ac4227b Mon Sep 17 00:00:00 2001 From: Nicholas Tay Date: Thu, 24 Mar 2022 16:32:23 +1100 Subject: Reorganise into folder groups In preparation for presenters to come in largely, lots of files starting to go everywhere... --- foray.xcodeproj/project.pbxproj | 38 ++++++-- foray/Coordinator.swift | 19 ---- foray/Coordinators/Coordinator.swift | 19 ++++ foray/Coordinators/ForayCoordinator.swift | 63 ++++++++++++ foray/Extensions/UIViewController+Extensions.swift | 23 +++++ foray/ForayCoordinator.swift | 63 ------------ foray/ForayDetailView.swift | 96 ------------------ foray/ForayDetailViewController.swift | 29 ------ foray/ForayLoadingOverlay.swift | 37 ------- foray/ForayNewTableViewCell.swift | 84 ---------------- foray/ForayTableViewController.swift | 107 --------------------- foray/Scenes/ForayDetailView.swift | 96 ++++++++++++++++++ foray/Scenes/ForayDetailViewController.swift | 29 ++++++ foray/Scenes/ForayLoadingOverlay.swift | 37 +++++++ foray/Scenes/ForayNewTableViewCell.swift | 84 ++++++++++++++++ foray/Scenes/ForayTableViewController.swift | 107 +++++++++++++++++++++ foray/UIViewController+Extensions.swift | 23 ----- 17 files changed, 489 insertions(+), 465 deletions(-) delete mode 100644 foray/Coordinator.swift create mode 100644 foray/Coordinators/Coordinator.swift create mode 100644 foray/Coordinators/ForayCoordinator.swift create mode 100644 foray/Extensions/UIViewController+Extensions.swift delete mode 100644 foray/ForayCoordinator.swift delete mode 100644 foray/ForayDetailView.swift delete mode 100644 foray/ForayDetailViewController.swift delete mode 100644 foray/ForayLoadingOverlay.swift delete mode 100644 foray/ForayNewTableViewCell.swift delete mode 100644 foray/ForayTableViewController.swift create mode 100644 foray/Scenes/ForayDetailView.swift create mode 100644 foray/Scenes/ForayDetailViewController.swift create mode 100644 foray/Scenes/ForayLoadingOverlay.swift create mode 100644 foray/Scenes/ForayNewTableViewCell.swift create mode 100644 foray/Scenes/ForayTableViewController.swift delete mode 100644 foray/UIViewController+Extensions.swift diff --git a/foray.xcodeproj/project.pbxproj b/foray.xcodeproj/project.pbxproj index f73a315..e25da72 100644 --- a/foray.xcodeproj/project.pbxproj +++ b/foray.xcodeproj/project.pbxproj @@ -72,22 +72,46 @@ C04B45A227DEF117001451A3 /* foray */ = { isa = PBXGroup; children = ( + C09676C327EC358F00353D46 /* Coordinators */, + C09676C227EC354700353D46 /* Extensions */, + C09676C127EC353D00353D46 /* Scenes */, C04B45A327DEF117001451A3 /* AppDelegate.swift */, C04B45A527DEF117001451A3 /* SceneDelegate.swift */, - C0FEAF5E27E14C52000A7648 /* ForayDetailViewController.swift */, - C04B45B727DEF2ED001451A3 /* ForayTableViewController.swift */, C011E4F227E6216C00C248D6 /* ForayItems.swift */, - C04EDE4327E4298D00D83005 /* ForayNewTableViewCell.swift */, C011E4F027E6211400C248D6 /* ForayNetworkManager.swift */, C04B45AC27DEF118001451A3 /* Assets.xcassets */, C04B45B127DEF118001451A3 /* Info.plist */, - C049BBFD27E82B9E003820A9 /* Coordinator.swift */, - C049BBFF27E82C90003820A9 /* ForayCoordinator.swift */, + ); + path = foray; + sourceTree = ""; + }; + C09676C127EC353D00353D46 /* Scenes */ = { + isa = PBXGroup; + children = ( + C04B45B727DEF2ED001451A3 /* ForayTableViewController.swift */, + C04EDE4327E4298D00D83005 /* ForayNewTableViewCell.swift */, + C0FEAF5E27E14C52000A7648 /* ForayDetailViewController.swift */, + C09676BD27EC28B100353D46 /* ForayDetailView.swift */, C09676B927E86B6E00353D46 /* ForayLoadingOverlay.swift */, + ); + path = Scenes; + sourceTree = ""; + }; + C09676C227EC354700353D46 /* Extensions */ = { + isa = PBXGroup; + children = ( C09676BB27EC27E700353D46 /* UIViewController+Extensions.swift */, - C09676BD27EC28B100353D46 /* ForayDetailView.swift */, ); - path = foray; + path = Extensions; + sourceTree = ""; + }; + C09676C327EC358F00353D46 /* Coordinators */ = { + isa = PBXGroup; + children = ( + C049BBFD27E82B9E003820A9 /* Coordinator.swift */, + C049BBFF27E82C90003820A9 /* ForayCoordinator.swift */, + ); + path = Coordinators; sourceTree = ""; }; /* End PBXGroup section */ diff --git a/foray/Coordinator.swift b/foray/Coordinator.swift deleted file mode 100644 index db97a1d..0000000 --- a/foray/Coordinator.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// Coordinator.swift -// foray -// -// Created by Nicholas Tay on 21/3/2022. -// Based on code from Paul Hudson on Hacking with Swift -// (https://www.hackingwithswift.com/articles/71/how-to-use-the-coordinator-pattern-in-ios-apps) -// - -import Foundation -import UIKit - -protocol Coordinator { - var childCoordinators: [Coordinator] { get set } - var navigationController: UINavigationController { get set } - - func start() -} - diff --git a/foray/Coordinators/Coordinator.swift b/foray/Coordinators/Coordinator.swift new file mode 100644 index 0000000..db97a1d --- /dev/null +++ b/foray/Coordinators/Coordinator.swift @@ -0,0 +1,19 @@ +// +// Coordinator.swift +// foray +// +// Created by Nicholas Tay on 21/3/2022. +// Based on code from Paul Hudson on Hacking with Swift +// (https://www.hackingwithswift.com/articles/71/how-to-use-the-coordinator-pattern-in-ios-apps) +// + +import Foundation +import UIKit + +protocol Coordinator { + var childCoordinators: [Coordinator] { get set } + var navigationController: UINavigationController { get set } + + func start() +} + diff --git a/foray/Coordinators/ForayCoordinator.swift b/foray/Coordinators/ForayCoordinator.swift new file mode 100644 index 0000000..6497ec0 --- /dev/null +++ b/foray/Coordinators/ForayCoordinator.swift @@ -0,0 +1,63 @@ +// +// ForayCoordinator.swift +// foray +// +// Created by Nicholas Tay on 21/3/2022. +// + +import Foundation +import UIKit + +protocol ForayCoordinated: UIViewController { + var coordinator: ForayCoordinator? { get set } +} + +class ForayCoordinator: Coordinator { + var childCoordinators = [Coordinator]() + var navigationController: UINavigationController + var loadingOverlay: ForayLoadingOverlay + + init(navigationController: UINavigationController) { + self.navigationController = navigationController + self.loadingOverlay = ForayLoadingOverlay(viewController: navigationController) + } + + private func push(vc: ForayCoordinated, animated: Bool = true) { + vc.coordinator = self + navigationController.pushViewController(vc, animated: animated) + } + + func start() { + push(vc: ForayTableViewController(), animated: false) + } + + let detailViewController = ForayDetailViewController() + + func showDetails(item: PenguinItem) { + let image: UIImage + var description: String = "Type: " + switch item.type { + case .item: + description += "Item" + image = UIImage(named: item.id)! + case .quest: + description += "Quest" + image = UIImage(named: "spy")! + } + description += "\nID: " + item.id + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd" + description += "\nReleased: " + dateFormatter.string(from: item.releaseDate) + + detailViewController.setDetails(name: item.name, description: description, image: image) + push(vc: detailViewController) + } + + func showLoading() { + loadingOverlay.show() + } + + func hideLoading() { + loadingOverlay.hide() + } +} diff --git a/foray/Extensions/UIViewController+Extensions.swift b/foray/Extensions/UIViewController+Extensions.swift new file mode 100644 index 0000000..ee2c436 --- /dev/null +++ b/foray/Extensions/UIViewController+Extensions.swift @@ -0,0 +1,23 @@ +// +// UIViewController+Extensions.swift +// foray +// +// Created by Nicholas Tay on 24/3/2022. +// + +import Foundation +import UIKit + +protocol HasCustomView { + associatedtype CustomView: UIView +} + +extension HasCustomView where Self: UIViewController { + internal var customView: CustomView { + guard let view = self.view as? CustomView else { + fatalError("Could not cast custom view") + } + + return view + } +} diff --git a/foray/ForayCoordinator.swift b/foray/ForayCoordinator.swift deleted file mode 100644 index 6497ec0..0000000 --- a/foray/ForayCoordinator.swift +++ /dev/null @@ -1,63 +0,0 @@ -// -// ForayCoordinator.swift -// foray -// -// Created by Nicholas Tay on 21/3/2022. -// - -import Foundation -import UIKit - -protocol ForayCoordinated: UIViewController { - var coordinator: ForayCoordinator? { get set } -} - -class ForayCoordinator: Coordinator { - var childCoordinators = [Coordinator]() - var navigationController: UINavigationController - var loadingOverlay: ForayLoadingOverlay - - init(navigationController: UINavigationController) { - self.navigationController = navigationController - self.loadingOverlay = ForayLoadingOverlay(viewController: navigationController) - } - - private func push(vc: ForayCoordinated, animated: Bool = true) { - vc.coordinator = self - navigationController.pushViewController(vc, animated: animated) - } - - func start() { - push(vc: ForayTableViewController(), animated: false) - } - - let detailViewController = ForayDetailViewController() - - func showDetails(item: PenguinItem) { - let image: UIImage - var description: String = "Type: " - switch item.type { - case .item: - description += "Item" - image = UIImage(named: item.id)! - case .quest: - description += "Quest" - image = UIImage(named: "spy")! - } - description += "\nID: " + item.id - let dateFormatter = DateFormatter() - dateFormatter.dateFormat = "yyyy-MM-dd" - description += "\nReleased: " + dateFormatter.string(from: item.releaseDate) - - detailViewController.setDetails(name: item.name, description: description, image: image) - push(vc: detailViewController) - } - - func showLoading() { - loadingOverlay.show() - } - - func hideLoading() { - loadingOverlay.hide() - } -} diff --git a/foray/ForayDetailView.swift b/foray/ForayDetailView.swift deleted file mode 100644 index 5997016..0000000 --- a/foray/ForayDetailView.swift +++ /dev/null @@ -1,96 +0,0 @@ -// -// ForayDetailView.swift -// foray -// -// Created by Nicholas Tay on 24/3/2022. -// - -import UIKit - -class ForayDetailView: UIView { - - let scrollView: UIScrollView = { - let sv = UIScrollView() - sv.alwaysBounceVertical = true // just for fun - return sv - }() - let container = UIView() - - let nameLabel: UILabel = { - let l = UILabel() - l.font = UIFont.preferredFont(forTextStyle: .largeTitle) - l.adjustsFontForContentSizeCategory = true - l.numberOfLines = 3 - l.textAlignment = .center - return l - }() - - let itemImageView: UIImageView = { - let iv = UIImageView() - iv.contentMode = .scaleAspectFit - return iv - }() - - let descLabel: UILabel = { - let l = UILabel() - l.font = UIFont.preferredFont(forTextStyle: .body) - l.adjustsFontForContentSizeCategory = true - l.numberOfLines = 10 - return l - }() - - override init(frame: CGRect) { - super.init(frame: frame) - initialiseViews() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - private func initialiseViews() { - backgroundColor = .systemBackground - - addSubview(scrollView) - scrollView.addSubview(container) - - container.addSubview(nameLabel) - container.addSubview(itemImageView) - container.addSubview(descLabel) - - setupConstraints() - } - - private func setupConstraints() { - scrollView.snp.makeConstraints { (make) in - make.edges.equalToSuperview() - } - container.snp.makeConstraints { (make) in - make.top.bottom.equalToSuperview() - make.leading.equalTo(snp.leadingMargin) - make.trailing.equalTo(snp.trailingMargin) - } - - nameLabel.snp.makeConstraints { (make) in - make.top.equalToSuperview().inset(16) - make.leading.trailing.equalToSuperview().inset(8) - } - itemImageView.snp.makeConstraints { (make) in - make.top.equalTo(nameLabel.snp.bottom).offset(32) - make.leading.trailing.equalToSuperview() - make.height.equalTo(150) - } - descLabel.snp.makeConstraints { (make) in - make.top.equalTo(itemImageView.snp.bottom).offset(32) - make.leading.trailing.equalToSuperview() - make.bottom.equalTo(container.snp.bottom).inset(16) - } - } - - public func setDetails(name: String, description: String, image: UIImage) { - nameLabel.text = name - descLabel.text = description - itemImageView.image = image - } - -} diff --git a/foray/ForayDetailViewController.swift b/foray/ForayDetailViewController.swift deleted file mode 100644 index c676df6..0000000 --- a/foray/ForayDetailViewController.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// ForayDetailViewController.swift -// foray -// -// Created by Nicholas Tay on 16/3/2022. -// - -import UIKit - -class ForayDetailViewController: UIViewController, HasCustomView, ForayCoordinated { - - typealias CustomView = ForayDetailView - - var coordinator: ForayCoordinator? - - override func viewDidLoad() { - super.viewDidLoad() - self.title = "Details" - } - - override func loadView() { - view = ForayDetailView() - } - - public func setDetails(name: String, description: String, image: UIImage) { - self.customView.setDetails(name: name, description: description, image: image) - } - -} diff --git a/foray/ForayLoadingOverlay.swift b/foray/ForayLoadingOverlay.swift deleted file mode 100644 index 1aa6260..0000000 --- a/foray/ForayLoadingOverlay.swift +++ /dev/null @@ -1,37 +0,0 @@ -// -// ForayLoadingOverlay.swift -// foray -// -// Created by Nicholas Tay on 21/3/2022. -// - -import UIKit - -class ForayLoadingOverlay { - - var viewController: UIViewController - - let loadingIndicator: UIActivityIndicatorView = { - let aiv = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50)) - aiv.hidesWhenStopped = true - aiv.style = UIActivityIndicatorView.Style.medium - aiv.startAnimating() - return aiv - }() - - let alert: UIAlertController = UIAlertController(title: nil, message: "Grabbing data...", preferredStyle: .alert) - - init(viewController: UIViewController) { - self.viewController = viewController - alert.view.addSubview(self.loadingIndicator) - } - - func show() { - viewController.present(alert, animated: true) - } - - func hide() { - viewController.dismiss(animated: false) - } - -} diff --git a/foray/ForayNewTableViewCell.swift b/foray/ForayNewTableViewCell.swift deleted file mode 100644 index 224709a..0000000 --- a/foray/ForayNewTableViewCell.swift +++ /dev/null @@ -1,84 +0,0 @@ -// -// ForayNewTableViewCell.swift -// foray -// -// Created by Nicholas Tay on 18/3/2022. -// - -import UIKit -import SnapKit - -class ForayNewTableViewCell: UITableViewCell { - - let container: UIView = UIView() - - let nameLabel: UILabel = { - let l = UILabel() - l.font = UIFont.preferredFont(forTextStyle: .headline) - l.numberOfLines = 3 - l.adjustsFontForContentSizeCategory = true - return l - }() - - let descLabel: UILabel = { - let l = UILabel() - l.font = UIFont.preferredFont(forTextStyle: .caption1) - l.adjustsFontForContentSizeCategory = true - return l - }() - - let itemImageView: UIImageView = { - let iv = UIImageView() - iv.contentMode = .scaleAspectFit - return iv - }() - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - initialiseViews() - } - - required init?(coder: NSCoder) { - fatalError("unreachable") - } - - private func initialiseViews() { - contentView.addSubview(container) - container.addSubview(nameLabel) - container.addSubview(descLabel) - container.addSubview(itemImageView) - setupConstraints() - } - - private func setupConstraints() { - container.snp.makeConstraints { (make) in - make.edges.equalTo(contentView.snp.margins) - } - - let imageWidth = 64 - let imageHeight = 38 - nameLabel.snp.makeConstraints { (make) in - make.top.equalToSuperview() - make.leading.equalToSuperview() - make.trailing.equalTo(itemImageView.snp.trailing).inset(imageWidth) - } - descLabel.snp.makeConstraints { (make) in - make.top.equalTo(nameLabel.snp.bottom) - make.leading.equalToSuperview() - make.bottom.equalToSuperview() - make.trailing.equalTo(itemImageView.snp.trailing).inset(imageWidth) - } - itemImageView.snp.makeConstraints { (make) in - make.top.equalToSuperview() - make.trailing.equalToSuperview() - make.width.equalTo(imageWidth) - make.height.equalTo(imageHeight) - } - } - - public func setData(name: String, desc: String, img: UIImage) { - nameLabel.text = name - descLabel.text = desc - itemImageView.image = img - } -} diff --git a/foray/ForayTableViewController.swift b/foray/ForayTableViewController.swift deleted file mode 100644 index 37ac2e5..0000000 --- a/foray/ForayTableViewController.swift +++ /dev/null @@ -1,107 +0,0 @@ -// -// ForayTableViewController.swift -// foray -// -// Created by Nicholas Tay on 14/3/2022. -// - -import UIKit - -class ForayTableViewController: UITableViewController, ForayCoordinated { - - var coordinator: ForayCoordinator? - - // MARK: - Static data TEMP - - var sections = [YearSection]() - - // MARK: - On load - - override func viewDidLoad() { - super.viewDidLoad() - self.title = "Foray" - - tableView.rowHeight = UITableView.automaticDimension - - // Register our custom cell - tableView.register(ForayNewTableViewCell.self, forCellReuseIdentifier: "ForayNewTableViewCell") - - // Not sure if this is the right way to go about this... - coordinator?.showLoading() - reloadApiData() - - self.refreshControl = UIRefreshControl() - self.refreshControl?.addTarget(self, action: #selector(doRefresh), for: UIControl.Event.valueChanged) - } - - @objc func doRefresh(sender: AnyObject) { - reloadApiData() - } - - func reloadApiData() { - ForayNetworkManager.shared.get( - url: "https://users.windblume.net/~nick/upload/dummy.json", - onComplete: { (apiItems: [PenguinItem]) in - var items = apiItems - - // Show items in chronological order within sections - items.sort { (lhs, rhs) in lhs.releaseDate < rhs.releaseDate } - - // Group by year sections - let groups = Dictionary(grouping: apiItems) { (item) in - return Calendar.current.component(.year, from: item.releaseDate) - } - self.sections = groups.map { (key, values) in - return YearSection(year: key, items: values) - } - // Sort the sections from oldest year to newest - self.sections.sort { (lhs, rhs) in lhs.year < rhs.year } - - self.tableView.reloadData() - self.refreshControl?.endRefreshing() - self.coordinator?.hideLoading() - }) - } - - // MARK: - Table view data source - - override func numberOfSections(in tableView: UITableView) -> Int { - // Returns number of sections for table - return self.sections.count - } - - override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - // Returns number of rows for table's section - return self.sections[section].items.count - } - - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let item = self.sections[indexPath.section].items[indexPath.row] - - let type: String - let icon: UIImage - switch item.type { - case .item: - type = "Item" - icon = UIImage(named: item.id)! - case .quest: - type = "Quest" - icon = UIImage(named: "spy")! - } - - let cell: ForayNewTableViewCell = tableView.dequeueReusableCell(withIdentifier: "ForayNewTableViewCell", for: indexPath) as! ForayNewTableViewCell - cell.setData(name: item.name, desc: type + "ID: " + item.id, img: icon) - return cell - } - - override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { - return "Released in \(self.sections[section].year)" - } - - override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - tableView.deselectRow(at: indexPath, animated: true) - - let item = self.sections[indexPath.section].items[indexPath.row] - self.coordinator?.showDetails(item: item) - } -} diff --git a/foray/Scenes/ForayDetailView.swift b/foray/Scenes/ForayDetailView.swift new file mode 100644 index 0000000..5997016 --- /dev/null +++ b/foray/Scenes/ForayDetailView.swift @@ -0,0 +1,96 @@ +// +// ForayDetailView.swift +// foray +// +// Created by Nicholas Tay on 24/3/2022. +// + +import UIKit + +class ForayDetailView: UIView { + + let scrollView: UIScrollView = { + let sv = UIScrollView() + sv.alwaysBounceVertical = true // just for fun + return sv + }() + let container = UIView() + + let nameLabel: UILabel = { + let l = UILabel() + l.font = UIFont.preferredFont(forTextStyle: .largeTitle) + l.adjustsFontForContentSizeCategory = true + l.numberOfLines = 3 + l.textAlignment = .center + return l + }() + + let itemImageView: UIImageView = { + let iv = UIImageView() + iv.contentMode = .scaleAspectFit + return iv + }() + + let descLabel: UILabel = { + let l = UILabel() + l.font = UIFont.preferredFont(forTextStyle: .body) + l.adjustsFontForContentSizeCategory = true + l.numberOfLines = 10 + return l + }() + + override init(frame: CGRect) { + super.init(frame: frame) + initialiseViews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func initialiseViews() { + backgroundColor = .systemBackground + + addSubview(scrollView) + scrollView.addSubview(container) + + container.addSubview(nameLabel) + container.addSubview(itemImageView) + container.addSubview(descLabel) + + setupConstraints() + } + + private func setupConstraints() { + scrollView.snp.makeConstraints { (make) in + make.edges.equalToSuperview() + } + container.snp.makeConstraints { (make) in + make.top.bottom.equalToSuperview() + make.leading.equalTo(snp.leadingMargin) + make.trailing.equalTo(snp.trailingMargin) + } + + nameLabel.snp.makeConstraints { (make) in + make.top.equalToSuperview().inset(16) + make.leading.trailing.equalToSuperview().inset(8) + } + itemImageView.snp.makeConstraints { (make) in + make.top.equalTo(nameLabel.snp.bottom).offset(32) + make.leading.trailing.equalToSuperview() + make.height.equalTo(150) + } + descLabel.snp.makeConstraints { (make) in + make.top.equalTo(itemImageView.snp.bottom).offset(32) + make.leading.trailing.equalToSuperview() + make.bottom.equalTo(container.snp.bottom).inset(16) + } + } + + public func setDetails(name: String, description: String, image: UIImage) { + nameLabel.text = name + descLabel.text = description + itemImageView.image = image + } + +} diff --git a/foray/Scenes/ForayDetailViewController.swift b/foray/Scenes/ForayDetailViewController.swift new file mode 100644 index 0000000..c676df6 --- /dev/null +++ b/foray/Scenes/ForayDetailViewController.swift @@ -0,0 +1,29 @@ +// +// ForayDetailViewController.swift +// foray +// +// Created by Nicholas Tay on 16/3/2022. +// + +import UIKit + +class ForayDetailViewController: UIViewController, HasCustomView, ForayCoordinated { + + typealias CustomView = ForayDetailView + + var coordinator: ForayCoordinator? + + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Details" + } + + override func loadView() { + view = ForayDetailView() + } + + public func setDetails(name: String, description: String, image: UIImage) { + self.customView.setDetails(name: name, description: description, image: image) + } + +} diff --git a/foray/Scenes/ForayLoadingOverlay.swift b/foray/Scenes/ForayLoadingOverlay.swift new file mode 100644 index 0000000..1aa6260 --- /dev/null +++ b/foray/Scenes/ForayLoadingOverlay.swift @@ -0,0 +1,37 @@ +// +// ForayLoadingOverlay.swift +// foray +// +// Created by Nicholas Tay on 21/3/2022. +// + +import UIKit + +class ForayLoadingOverlay { + + var viewController: UIViewController + + let loadingIndicator: UIActivityIndicatorView = { + let aiv = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50)) + aiv.hidesWhenStopped = true + aiv.style = UIActivityIndicatorView.Style.medium + aiv.startAnimating() + return aiv + }() + + let alert: UIAlertController = UIAlertController(title: nil, message: "Grabbing data...", preferredStyle: .alert) + + init(viewController: UIViewController) { + self.viewController = viewController + alert.view.addSubview(self.loadingIndicator) + } + + func show() { + viewController.present(alert, animated: true) + } + + func hide() { + viewController.dismiss(animated: false) + } + +} diff --git a/foray/Scenes/ForayNewTableViewCell.swift b/foray/Scenes/ForayNewTableViewCell.swift new file mode 100644 index 0000000..224709a --- /dev/null +++ b/foray/Scenes/ForayNewTableViewCell.swift @@ -0,0 +1,84 @@ +// +// ForayNewTableViewCell.swift +// foray +// +// Created by Nicholas Tay on 18/3/2022. +// + +import UIKit +import SnapKit + +class ForayNewTableViewCell: UITableViewCell { + + let container: UIView = UIView() + + let nameLabel: UILabel = { + let l = UILabel() + l.font = UIFont.preferredFont(forTextStyle: .headline) + l.numberOfLines = 3 + l.adjustsFontForContentSizeCategory = true + return l + }() + + let descLabel: UILabel = { + let l = UILabel() + l.font = UIFont.preferredFont(forTextStyle: .caption1) + l.adjustsFontForContentSizeCategory = true + return l + }() + + let itemImageView: UIImageView = { + let iv = UIImageView() + iv.contentMode = .scaleAspectFit + return iv + }() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + initialiseViews() + } + + required init?(coder: NSCoder) { + fatalError("unreachable") + } + + private func initialiseViews() { + contentView.addSubview(container) + container.addSubview(nameLabel) + container.addSubview(descLabel) + container.addSubview(itemImageView) + setupConstraints() + } + + private func setupConstraints() { + container.snp.makeConstraints { (make) in + make.edges.equalTo(contentView.snp.margins) + } + + let imageWidth = 64 + let imageHeight = 38 + nameLabel.snp.makeConstraints { (make) in + make.top.equalToSuperview() + make.leading.equalToSuperview() + make.trailing.equalTo(itemImageView.snp.trailing).inset(imageWidth) + } + descLabel.snp.makeConstraints { (make) in + make.top.equalTo(nameLabel.snp.bottom) + make.leading.equalToSuperview() + make.bottom.equalToSuperview() + make.trailing.equalTo(itemImageView.snp.trailing).inset(imageWidth) + } + itemImageView.snp.makeConstraints { (make) in + make.top.equalToSuperview() + make.trailing.equalToSuperview() + make.width.equalTo(imageWidth) + make.height.equalTo(imageHeight) + } + } + + public func setData(name: String, desc: String, img: UIImage) { + nameLabel.text = name + descLabel.text = desc + itemImageView.image = img + } +} diff --git a/foray/Scenes/ForayTableViewController.swift b/foray/Scenes/ForayTableViewController.swift new file mode 100644 index 0000000..37ac2e5 --- /dev/null +++ b/foray/Scenes/ForayTableViewController.swift @@ -0,0 +1,107 @@ +// +// ForayTableViewController.swift +// foray +// +// Created by Nicholas Tay on 14/3/2022. +// + +import UIKit + +class ForayTableViewController: UITableViewController, ForayCoordinated { + + var coordinator: ForayCoordinator? + + // MARK: - Static data TEMP + + var sections = [YearSection]() + + // MARK: - On load + + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Foray" + + tableView.rowHeight = UITableView.automaticDimension + + // Register our custom cell + tableView.register(ForayNewTableViewCell.self, forCellReuseIdentifier: "ForayNewTableViewCell") + + // Not sure if this is the right way to go about this... + coordinator?.showLoading() + reloadApiData() + + self.refreshControl = UIRefreshControl() + self.refreshControl?.addTarget(self, action: #selector(doRefresh), for: UIControl.Event.valueChanged) + } + + @objc func doRefresh(sender: AnyObject) { + reloadApiData() + } + + func reloadApiData() { + ForayNetworkManager.shared.get( + url: "https://users.windblume.net/~nick/upload/dummy.json", + onComplete: { (apiItems: [PenguinItem]) in + var items = apiItems + + // Show items in chronological order within sections + items.sort { (lhs, rhs) in lhs.releaseDate < rhs.releaseDate } + + // Group by year sections + let groups = Dictionary(grouping: apiItems) { (item) in + return Calendar.current.component(.year, from: item.releaseDate) + } + self.sections = groups.map { (key, values) in + return YearSection(year: key, items: values) + } + // Sort the sections from oldest year to newest + self.sections.sort { (lhs, rhs) in lhs.year < rhs.year } + + self.tableView.reloadData() + self.refreshControl?.endRefreshing() + self.coordinator?.hideLoading() + }) + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { + // Returns number of sections for table + return self.sections.count + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + // Returns number of rows for table's section + return self.sections[section].items.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let item = self.sections[indexPath.section].items[indexPath.row] + + let type: String + let icon: UIImage + switch item.type { + case .item: + type = "Item" + icon = UIImage(named: item.id)! + case .quest: + type = "Quest" + icon = UIImage(named: "spy")! + } + + let cell: ForayNewTableViewCell = tableView.dequeueReusableCell(withIdentifier: "ForayNewTableViewCell", for: indexPath) as! ForayNewTableViewCell + cell.setData(name: item.name, desc: type + "ID: " + item.id, img: icon) + return cell + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + return "Released in \(self.sections[section].year)" + } + + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + + let item = self.sections[indexPath.section].items[indexPath.row] + self.coordinator?.showDetails(item: item) + } +} diff --git a/foray/UIViewController+Extensions.swift b/foray/UIViewController+Extensions.swift deleted file mode 100644 index ee2c436..0000000 --- a/foray/UIViewController+Extensions.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// UIViewController+Extensions.swift -// foray -// -// Created by Nicholas Tay on 24/3/2022. -// - -import Foundation -import UIKit - -protocol HasCustomView { - associatedtype CustomView: UIView -} - -extension HasCustomView where Self: UIViewController { - internal var customView: CustomView { - guard let view = self.view as? CustomView else { - fatalError("Could not cast custom view") - } - - return view - } -} -- cgit