Files
eqn.ios/Sources/Earthquake Network/Controllers/Seismic Networks/SeismicNetworksViewController.swift
T
2020-09-26 18:31:00 +02:00

327 lines
12 KiB
Swift

//
// SeismicNetworksViewController.swift
// Earthquake Network
//
// Created by Busi Andrea on 22/09/2020.
// Copyright © 2020 Earthquake Network. All rights reserved.
//
import UIKit
import EventKitUI
import DZNEmptyDataSet
class SeismicNetworksViewController: EQNBaseViewController, UITableViewDelegate, UITableViewDataSource {
private static let SegueIdentifierMap = "ShowMapDetail"
private static let SegueIdentifierFilters = "ShowFilters"
private static let SegueIdentifierSettings = "ShowSettings"
private static let SegueIdentifierSeismicNetworks = "ShowSeismicNetworks"
private static let SegueIdentifierCardSettings = "ShowCardSettings"
// MARK: - Internal
@IBOutlet private weak var tableView: UITableView?
@IBOutlet private weak var expandeCollapseButton: UIBarButtonItem!
/// Seismisc to display
private var seismics = [EQNSisma]()
/// Informations to display on a single cell
private var informations = [SeismicNetworkTableViewCell.InformationType]()
/// Index path of row with map expanded
private var openMapIndexPath: IndexPath?
/// Index path of row with weather expanded
private var openWeatherIndexPath: IndexPath?
// MARK: - View Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self,
selector: #selector(didReceiveDownloadCompletedNotification(_:)),
name: NSNotification.Name(rawValue: NOTIFICA_DOWNLOAD_TERMINATO),
object: nil)
setupUI()
refreshUI()
}
private func setupUI() {
title = NSLocalizedString("tab_official", comment: "")
tableView?.estimatedRowHeight = 300.0;
tableView?.rowHeight = UITableView.automaticDimension
tableView?.register(SeismicNetworkTableViewCell.self, forCellReuseIdentifier: SeismicNetworkTableViewCell.Identifier)
tableView?.emptyDataSetSource = self
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.identifier {
case Self.SegueIdentifierMap:
if let seismic = sender as? EQNSisma, let navController = segue.destination as? UINavigationController, let controller = navController.viewControllers.first as? ReteSismiDettagliMappa {
controller.sisma = seismic
}
case Self.SegueIdentifierFilters:
if let controller = segue.destination as? SeismicFiltersViewController {
controller.delegate = self
}
case Self.SegueIdentifierSettings:
if let controller = segue.destination as? SeismicSettingsViewController {
controller.delegate = self
}
case Self.SegueIdentifierSeismicNetworks:
if let navController = segue.destination as? UINavigationController, let controller = navController.viewControllers.first as? SeismicSettingsNetworksViewController {
controller.delegate = self
}
case Self.SegueIdentifierCardSettings:
if let controller = segue.destination as? SeismicCardSettingsViewController {
controller.delegate = self
}
default:
break
}
}
// MARK: - Notification
@objc func didReceiveDownloadCompletedNotification(_ notification: NSNotification) {
DispatchQueue.main.async {
self.refreshUI()
}
}
// MARK: - Private
override func refreshUI() {
super.refreshUI()
let allSeismics = EQNManager.manager().retiSismiche
seismics = EQNSeismic.shared.filterSeismicList(allSeismics ?? [])
if let saved = UserDefaults.standard.array(forKey: EQNUserDefaultKeySesmicInformations) as? [Int] {
informations = saved.compactMap { SeismicNetworkTableViewCell.InformationType(rawValue: $0) }
}
if informations.contains(.buttons) {
expandeCollapseButton.image = UIImage(named: "navbar-icon-arrow-collapse")
} else {
expandeCollapseButton.image = UIImage(named: "navbar-icon-arrow-expand")
}
tableView?.reloadData()
}
// MARK: - Actions
@IBAction func refreshDataTapped(_ sender: Any) {
EQNManager.manager().sincronizza()
}
@IBAction func openFilterTapped(_ sender: Any) {
performSegue(withIdentifier: Self.SegueIdentifierFilters, sender: nil)
}
@IBAction func openSettingsTapped(_ sender: Any) {
performSegue(withIdentifier: Self.SegueIdentifierSettings, sender: nil)
}
@IBAction func collapseExpandTapped(_ sender: Any) {
if informations.contains(.buttons) {
informations.removeAll(where: { $0 == .buttons })
} else {
informations.append(.buttons)
}
UserDefaults.standard.set(informations.map { $0.rawValue }, forKey: EQNUserDefaultKeySesmicInformations)
refreshUI()
}
// MARK: - Table view delegate and data source
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
seismics.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: SeismicNetworkTableViewCell.Identifier, for: indexPath) as! SeismicNetworkTableViewCell
let seismic = seismics[indexPath.row]
var type = SeismicNetworkTableViewCell.DisplayType.normal
if openMapIndexPath == indexPath {
type = .mapExpanded
} else if openWeatherIndexPath == indexPath {
type = .weatherExpanded
}
cell.configure(with: seismic, type: type, informations: informations)
cell.delegate = self
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let seismic = seismics[indexPath.row]
performSegue(withIdentifier: Self.SegueIdentifierMap, sender: seismic)
}
// MARK: - Private
private func openCalendar(for seismic: EQNSisma) {
checkCalendarPermission {
self.createCalendarEvent(for: seismic)
} failure: {
let alert = UIAlertController(title: NSLocalizedString("Attenzione", comment: ""),
message: "Non è possibile aprire il calendario, assicurarsi di aver impostato i permessi corretti",
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default))
self.present(alert, animated: true)
}
}
private func checkCalendarPermission(success: @escaping () -> Void, failure: @escaping () -> Void) {
let authorization = EKEventStore.authorizationStatus(for: .event)
switch authorization {
case .notDetermined:
let eventStore = EKEventStore()
eventStore.requestAccess(to: .event) { (granted, error) in
DispatchQueue.main.async {
if granted {
success()
} else {
failure()
}
}
}
case .authorized:
success()
default:
failure()
}
}
private func createCalendarEvent(for seismic: EQNSisma) {
let eventStore = EKEventStore()
// calendar event
let event = EKEvent(eventStore: eventStore)
event.title = seismic.place
event.startDate = seismic.date
event.endDate = seismic.date
event.notes = String(format: NSLocalizedString("calendar_description_nogeo_km", comment: ""), seismic.magnitude, seismic.depth)
// controller to present
let eventVC = EKEventEditViewController()
eventVC.editViewDelegate = self
eventVC.eventStore = eventStore
eventVC.event = event
present(eventVC, animated: true)
}
}
extension SeismicNetworksViewController: SeismicNetworkTableViewCellDelegate {
func seismicNetworkCellDidTapShare(_ cell: SeismicNetworkTableViewCell) {
// create a snapshot of the cell and share with default share sheet
let snapshot = cell.createSnapshot()
let controller = UIActivityViewController(activityItems: [snapshot], applicationActivities: [])
present(controller, animated: true)
}
func seismicNetworkCellDidTapWeather(_ cell: SeismicNetworkTableViewCell) {
guard let index = tableView?.indexPath(for: cell) else { return }
let indexToReloads = [openMapIndexPath, openWeatherIndexPath, index].compactMap { $0 }
openWeatherIndexPath = index
openMapIndexPath = nil
tableView?.reloadRows(at: indexToReloads, with: .automatic)
}
func seismicNetworkCellDidTapMap(_ cell: SeismicNetworkTableViewCell) {
guard let index = tableView?.indexPath(for: cell) else { return }
let indexToReloads = [openMapIndexPath, openWeatherIndexPath, index].compactMap { $0 }
openMapIndexPath = index
openWeatherIndexPath = nil
tableView?.reloadRows(at: indexToReloads, with: .automatic)
}
func seismicNetworkCellDidTapMapDetail(_ cell: SeismicNetworkTableViewCell) {
guard let index = tableView?.indexPath(for: cell) else { return }
let seismic = seismics[index.row]
performSegue(withIdentifier: Self.SegueIdentifierMap, sender: seismic)
}
func seismicNetworkCellDidTapCalendar(_ cell: SeismicNetworkTableViewCell) {
guard let index = tableView?.indexPath(for: cell) else { return }
let seismic = seismics[index.row]
openCalendar(for: seismic)
}
func seismicNetworkCellDidTapSettings(_ cell: SeismicNetworkTableViewCell) {
performSegue(withIdentifier: Self.SegueIdentifierCardSettings, sender: nil)
}
func seismicNetworkCellDidTapClose(_ cell: SeismicNetworkTableViewCell) {
guard let index = tableView?.indexPath(for: cell) else { return }
let indexToReloads = [openMapIndexPath, openWeatherIndexPath, index].compactMap { $0 }
openMapIndexPath = nil
openWeatherIndexPath = nil
tableView?.reloadRows(at: indexToReloads, with: .automatic)
}
}
extension SeismicNetworksViewController: EKEventEditViewDelegate {
func eventEditViewController(_ controller: EKEventEditViewController, didCompleteWith action: EKEventEditViewAction) {
dismiss(animated: true, completion: nil)
}
}
extension SeismicNetworksViewController: SeismicFiltersViewControllerDelegate {
func seismicFiltersControllerDidUpdateFilters(_ controller: SeismicFiltersViewController) {
if controller.needsDataUpdate {
EQNManager.manager().sincronizza()
}
refreshUI()
}
}
extension SeismicNetworksViewController: SeismicSettingsViewControllerDelegate {
func seismicSettingsControllerDidComplete(_ controller: SeismicSettingsViewController) {
refreshUI()
}
func seismicSettingsControllerWillOpenProviders(_ controller: SeismicSettingsViewController) {
performSegue(withIdentifier: Self.SegueIdentifierSeismicNetworks, sender: nil)
}
}
extension SeismicNetworksViewController: SeismicSettingsNetworksViewControllerDelegate {
func seismicSettingsNetworksControllerDidComplete(_ controller: SeismicSettingsNetworksViewController) {
refreshUI()
}
}
extension SeismicNetworksViewController: SeismicCardSettingsViewControllerDelegate {
func seismicCardSettingsDidComplete(_ controller: SeismicCardSettingsViewController) {
refreshUI()
}
}
extension SeismicNetworksViewController: DZNEmptyDataSetSource {
func title(forEmptyDataSet scrollView: UIScrollView!) -> NSAttributedString! {
let attributes = [ NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .body) ]
let string = NSAttributedString(string: NSLocalizedString("filter_empty", comment: ""), attributes: attributes)
return string
}
}