feat: Add new minimal card in seismics list
Resolves: https://gitlab.steamware.net/eqn/eqn.ios/-/issues/87
This commit is contained in:
@@ -18,6 +18,8 @@
|
||||
6514FF6D2D720CBE000A7BD0 /* MapPinStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6514FF692D720C3A000A7BD0 /* MapPinStyle.swift */; };
|
||||
65172F532C25C496006D2A5C /* EQNSeismicAnnotationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65172F522C25C496006D2A5C /* EQNSeismicAnnotationView.swift */; };
|
||||
651901B925F5358700CAFF20 /* EQNMapAnnotationSeismic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 651901B825F5358700CAFF20 /* EQNMapAnnotationSeismic.swift */; };
|
||||
652247242D79DAA000D2B8DF /* SeismicNetworkMinimalTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 652247232D79DAA000D2B8DF /* SeismicNetworkMinimalTableViewCell.swift */; };
|
||||
652247262D79EC5E00D2B8DF /* SeismicNetworkBaseTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 652247252D79EC5E00D2B8DF /* SeismicNetworkBaseTableViewCell.swift */; };
|
||||
6525A82625E13FD4008FE0D0 /* SeismicNetworkAdvertiseTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6525A82525E13FD4008FE0D0 /* SeismicNetworkAdvertiseTableViewCell.swift */; };
|
||||
652A3C6B2A8A757800719796 /* EQNBackgrounPositionDebugViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 652A3C6A2A8A757800719796 /* EQNBackgrounPositionDebugViewController.swift */; };
|
||||
65355FFF25F38D3300BB57D2 /* SegnalazioniMapViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65355FFE25F38D3300BB57D2 /* SegnalazioniMapViewController.swift */; };
|
||||
@@ -320,6 +322,8 @@
|
||||
6514FF692D720C3A000A7BD0 /* MapPinStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapPinStyle.swift; sourceTree = "<group>"; };
|
||||
65172F522C25C496006D2A5C /* EQNSeismicAnnotationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNSeismicAnnotationView.swift; sourceTree = "<group>"; };
|
||||
651901B825F5358700CAFF20 /* EQNMapAnnotationSeismic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNMapAnnotationSeismic.swift; sourceTree = "<group>"; };
|
||||
652247232D79DAA000D2B8DF /* SeismicNetworkMinimalTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicNetworkMinimalTableViewCell.swift; sourceTree = "<group>"; };
|
||||
652247252D79EC5E00D2B8DF /* SeismicNetworkBaseTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicNetworkBaseTableViewCell.swift; sourceTree = "<group>"; };
|
||||
6525A82525E13FD4008FE0D0 /* SeismicNetworkAdvertiseTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeismicNetworkAdvertiseTableViewCell.swift; sourceTree = "<group>"; };
|
||||
652A3C6A2A8A757800719796 /* EQNBackgrounPositionDebugViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EQNBackgrounPositionDebugViewController.swift; sourceTree = "<group>"; };
|
||||
65355FFE25F38D3300BB57D2 /* SegnalazioniMapViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegnalazioniMapViewController.swift; sourceTree = "<group>"; };
|
||||
@@ -949,7 +953,9 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
65DBFB7D25E2CB020041CBA6 /* Ad templates */,
|
||||
652247252D79EC5E00D2B8DF /* SeismicNetworkBaseTableViewCell.swift */,
|
||||
DC28142F2519C24400C1AFF7 /* SeismicNetworkTableViewCell.swift */,
|
||||
652247232D79DAA000D2B8DF /* SeismicNetworkMinimalTableViewCell.swift */,
|
||||
6525A82525E13FD4008FE0D0 /* SeismicNetworkAdvertiseTableViewCell.swift */,
|
||||
);
|
||||
path = Cells;
|
||||
@@ -1595,8 +1601,10 @@
|
||||
650247122A61832F001AC512 /* EQNBackgroundPositionDebugHelper.swift in Sources */,
|
||||
65CB83432915720400EE1E35 /* EQNUserData.swift in Sources */,
|
||||
654D18C425F93C0600BB6DB0 /* PasquakesMapViewController.swift in Sources */,
|
||||
652247242D79DAA000D2B8DF /* SeismicNetworkMinimalTableViewCell.swift in Sources */,
|
||||
8C483CBC21FDACE500259FD2 /* EQNInAppProducts.swift in Sources */,
|
||||
8C483CB821FDACD300259FD2 /* IAPHelper.swift in Sources */,
|
||||
652247262D79EC5E00D2B8DF /* SeismicNetworkBaseTableViewCell.swift in Sources */,
|
||||
6562C80725FFA6B100C85273 /* SeismicNetworkViewModel.swift in Sources */,
|
||||
DCDE0BD924E58CCE00209778 /* EQNMainTabBarController.m in Sources */,
|
||||
8C4E344B2152EE5B008B0D2A /* EQNGeneratoreURLServer.m in Sources */,
|
||||
|
||||
@@ -60,6 +60,8 @@ extension UserDefaults {
|
||||
static let MapPinStyle = "EQNetwork.MapPinStyle"
|
||||
/// Indica le informazioni da visualizzare nelle card `small` e `full` nella Lista Sismi
|
||||
static let SeismicNetworksCardInformations = "EQNetwork.SeismicInformations";
|
||||
/// Indica la tipologia di card da visualizzare nella Lista Sismi
|
||||
static let SeismicNetworksCardStyle = "EQNetwork.SeismicNetworksCardStyle"
|
||||
|
||||
// Migrazioni
|
||||
static let AppMigrationV5_3 = "EQNUserDefaultMigrationV5_3"
|
||||
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
//
|
||||
// SeismicNetworkBaseTableViewCell.swift
|
||||
// Earthquake Network
|
||||
//
|
||||
// Created by Andrea Busi on 06/03/25.
|
||||
// Copyright © 2025 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Shogun
|
||||
|
||||
protocol SeismicNetworkBaseTableViewCellDelegate: AnyObject {
|
||||
func seismicNetworkCellDidTapShare(_ cell: SeismicNetworkBaseTableViewCell)
|
||||
func seismicNetworkCellDidTapMap(_ cell: SeismicNetworkBaseTableViewCell)
|
||||
func seismicNetworkCellDidTapMapDetail(_ cell: SeismicNetworkBaseTableViewCell)
|
||||
func seismicNetworkCellDidTapIntensityMapDetail(_ cell: SeismicNetworkBaseTableViewCell)
|
||||
func seismicNetworkCellDidTapCalendar(_ cell: SeismicNetworkBaseTableViewCell)
|
||||
func seismicNetworkCellDidTapSettings(_ cell: SeismicNetworkBaseTableViewCell)
|
||||
func seismicNetworkCellDidTapClose(_ cell: SeismicNetworkBaseTableViewCell)
|
||||
}
|
||||
|
||||
|
||||
class SeismicNetworkBaseTableViewCell: UITableViewCell {
|
||||
|
||||
/// Delegate
|
||||
weak var delegate: SeismicNetworkBaseTableViewCellDelegate?
|
||||
|
||||
/// Available informations to display inside the cell
|
||||
enum InformationType: Int {
|
||||
case preliminary
|
||||
case time
|
||||
case distance
|
||||
case coordinate
|
||||
case population
|
||||
case realtimeSmartphones
|
||||
case reportUsers
|
||||
case intensityMap
|
||||
case buttons
|
||||
}
|
||||
|
||||
// MARL: - Internal
|
||||
|
||||
static let DefaultButtonHeight: CGFloat = 34.0
|
||||
static let VerticalSpacingDefault: CGFloat = 6.0
|
||||
static let VerticalSpacingSmall: CGFloat = 2.0
|
||||
static let HorizontalSpacingDefault: CGFloat = 4.0
|
||||
|
||||
// MARK: - UI Components
|
||||
|
||||
lazy var containerView: UIView = {
|
||||
let view = UIView(frame: .zero)
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.backgroundColor = .white
|
||||
view.clipsToBounds = true
|
||||
return view
|
||||
}()
|
||||
|
||||
lazy var gradientView: UIImageView = {
|
||||
// Per gestire il gradiente, utilizziamo una image view in cui inseriamo un'immagine
|
||||
// creata ad-hoc con il gradiente desiderato.
|
||||
// Le prove fatte utilizzando una view normale sono fallite perchè al momento di
|
||||
// disegnare la view non abbiamo le misure corrette.
|
||||
let view = UIImageView(frame: .zero)
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.contentMode = .scaleToFill
|
||||
return view
|
||||
}()
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
setupUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
setupUI()
|
||||
}
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
containerView.eqn_applyShadowAndRoundedCorners()
|
||||
gradientView.eqn_applyRoundedCorners()
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
func setupUI() {
|
||||
selectionStyle = .default
|
||||
backgroundColor = .clear
|
||||
|
||||
// container view
|
||||
contentView.addSubview(containerView)
|
||||
containerView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 4.0).isActive = true
|
||||
containerView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8.0).isActive = true
|
||||
containerView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8.0).isActive = true
|
||||
containerView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -4.0).isActive = true
|
||||
|
||||
containerView.addSubview(gradientView)
|
||||
gradientView.constraint(to: containerView)
|
||||
}
|
||||
|
||||
func recreateUI() {
|
||||
// remove all subviews and recreate the required components
|
||||
containerView.subviews.forEach({ $0.removeFromSuperview() })
|
||||
setupUI()
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func addSeparator(constraintTo: NSLayoutYAxisAnchor, constanst: CGFloat = 8.0) -> UIView {
|
||||
let separator = UIView()
|
||||
separator.translatesAutoresizingMaskIntoConstraints = false
|
||||
separator.backgroundColor = .lightGray
|
||||
containerView.addSubview(separator)
|
||||
|
||||
separator.topAnchor.constraint(equalTo: constraintTo, constant: constanst).isActive = true
|
||||
separator.leadingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.leadingAnchor).isActive = true
|
||||
separator.trailingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.trailingAnchor).isActive = true
|
||||
separator.heightAnchor.constraint(equalToConstant: 1.0).isActive = true
|
||||
|
||||
return separator
|
||||
}
|
||||
}
|
||||
+232
@@ -0,0 +1,232 @@
|
||||
//
|
||||
// SeismicNetworkMinimalTableViewCell.swift
|
||||
// Earthquake Network
|
||||
//
|
||||
// Created by Andrea Busi on 06/03/25.
|
||||
// Copyright © 2025 Earthquake Network. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Shogun
|
||||
|
||||
|
||||
class SeismicNetworkMinimalTableViewCell: SeismicNetworkBaseTableViewCell {
|
||||
|
||||
// MARK: - UI
|
||||
|
||||
private lazy var magnitudeLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.font = UIFont.preferredFont(forTextStyle: .largeTitle)
|
||||
label.textColor = .red
|
||||
label.textAlignment = .center
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var placeLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.font = UIFont.preferredFont(forTextStyle: .title2, weight: .semibold)
|
||||
label.numberOfLines = 3
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var timeLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.font = .preferredFont(forTextStyle: .body)
|
||||
label.numberOfLines = 2
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var distanceLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.font = .preferredFont(forTextStyle: .body)
|
||||
label.numberOfLines = 2
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var smartphonesLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.numberOfLines = 0
|
||||
label.font = .preferredFont(forTextStyle: .body)
|
||||
label.textAlignment = .center
|
||||
label.numberOfLines = 2
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var alertsLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.numberOfLines = 0
|
||||
label.font = .preferredFont(forTextStyle: .body)
|
||||
label.textAlignment = .center
|
||||
label.numberOfLines = 2
|
||||
return label
|
||||
}()
|
||||
|
||||
// MARK: - Internal
|
||||
|
||||
/// Seismic to show
|
||||
private var seismic: EQNSisma?
|
||||
private var isPushSelected = false
|
||||
private var informationTypes: Set<InformationType> = []
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
override func setupUI() {
|
||||
super.setupUI()
|
||||
|
||||
// this variable is used to keep track of the previous view, in order to attach proper constraints
|
||||
var previousView: UIView = containerView
|
||||
|
||||
// preliminary banner on top of the cell
|
||||
if informationTypes.contains(.preliminary) {
|
||||
let preliminaryLabel = UILabel()
|
||||
preliminaryLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
preliminaryLabel.text = NSLocalizedString("official_prelimiary", comment: "").uppercased()
|
||||
preliminaryLabel.textAlignment = .center
|
||||
preliminaryLabel.backgroundColor = .red
|
||||
preliminaryLabel.textColor = .yellow
|
||||
|
||||
containerView.addSubview(preliminaryLabel)
|
||||
preliminaryLabel.heightAnchor.constraint(equalToConstant: 30.0).isActive = true
|
||||
preliminaryLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true
|
||||
preliminaryLabel.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true
|
||||
preliminaryLabel.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true
|
||||
|
||||
previousView = preliminaryLabel
|
||||
}
|
||||
|
||||
containerView.addSubview(magnitudeLabel)
|
||||
containerView.addSubview(placeLabel)
|
||||
|
||||
let titleTopAnchor = previousView == containerView ? containerView.layoutMarginsGuide.topAnchor : previousView.bottomAnchor
|
||||
|
||||
|
||||
let stackViewInformations = UIStackView(arrangedSubviews: [timeLabel, distanceLabel])
|
||||
stackViewInformations.translatesAutoresizingMaskIntoConstraints = false
|
||||
stackViewInformations.axis = .horizontal
|
||||
stackViewInformations.distribution = .fillEqually
|
||||
stackViewInformations.spacing = Self.HorizontalSpacingDefault
|
||||
containerView.addSubview(stackViewInformations)
|
||||
|
||||
let stackViewRight = UIStackView(arrangedSubviews: [placeLabel, stackViewInformations])
|
||||
stackViewRight.translatesAutoresizingMaskIntoConstraints = false
|
||||
stackViewRight.axis = .vertical
|
||||
stackViewRight.distribution = .equalSpacing
|
||||
stackViewRight.spacing = Self.VerticalSpacingDefault
|
||||
|
||||
let stackViewMain = UIStackView(arrangedSubviews: [magnitudeLabel, stackViewRight])
|
||||
stackViewMain.translatesAutoresizingMaskIntoConstraints = false
|
||||
stackViewMain.axis = .horizontal
|
||||
stackViewMain.distribution = .fill
|
||||
stackViewMain.spacing = Self.HorizontalSpacingDefault
|
||||
containerView.addSubview(stackViewMain)
|
||||
|
||||
stackViewMain.topAnchor.constraint(equalTo: titleTopAnchor).isActive = true
|
||||
stackViewMain.leadingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.leadingAnchor).isActive = true
|
||||
stackViewMain.trailingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.trailingAnchor).isActive = true
|
||||
magnitudeLabel.widthAnchor.constraint(equalToConstant: 60.0).isActive = true
|
||||
|
||||
previousView = stackViewMain
|
||||
|
||||
if informationTypes.contains(.realtimeSmartphones) || informationTypes.contains(.reportUsers) || informationTypes.contains(.intensityMap) {
|
||||
let separator = addSeparator(constraintTo: previousView.bottomAnchor, constanst: Self.VerticalSpacingDefault)
|
||||
|
||||
let stackViewReports = UIStackView()
|
||||
stackViewReports.translatesAutoresizingMaskIntoConstraints = false
|
||||
stackViewReports.axis = .vertical
|
||||
stackViewReports.distribution = .equalSpacing
|
||||
stackViewReports.alignment = .center
|
||||
stackViewReports.spacing = Self.VerticalSpacingDefault
|
||||
|
||||
if informationTypes.contains(.realtimeSmartphones) {
|
||||
stackViewReports.addArrangedSubview(smartphonesLabel)
|
||||
}
|
||||
if informationTypes.contains(.reportUsers) {
|
||||
stackViewReports.addArrangedSubview(alertsLabel)
|
||||
}
|
||||
if informationTypes.contains(.intensityMap) {
|
||||
let buttonMap = EQNRoundedButton.make(title: "🎯 \(NSLocalizedString("shakemap", comment: ""))", target: self, action: #selector(intensityMapTapped(_:)))
|
||||
stackViewReports.addArrangedSubview(buttonMap)
|
||||
buttonMap.heightAnchor.constraint(equalToConstant: Self.DefaultButtonHeight).isActive = true
|
||||
buttonMap.leadingAnchor.constraint(equalTo: stackViewReports.leadingAnchor).isActive = true
|
||||
buttonMap.trailingAnchor.constraint(equalTo: stackViewReports.trailingAnchor).isActive = true
|
||||
}
|
||||
|
||||
containerView.addSubview(stackViewReports)
|
||||
stackViewReports.topAnchor.constraint(equalTo: separator.bottomAnchor, constant: Self.VerticalSpacingDefault).isActive = true
|
||||
stackViewReports.leadingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.leadingAnchor).isActive = true
|
||||
stackViewReports.trailingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.trailingAnchor).isActive = true
|
||||
|
||||
previousView = stackViewReports
|
||||
}
|
||||
|
||||
previousView.bottomAnchor.constraint(equalTo: containerView.layoutMarginsGuide.bottomAnchor).isActive = true
|
||||
|
||||
containerView.eqn_applyShadowAndRoundedCorners()
|
||||
gradientView.eqn_applyRoundedCorners()
|
||||
}
|
||||
|
||||
private func updateUI() {
|
||||
guard let seismic = seismic else { return }
|
||||
|
||||
let viewModel = SeismicNetworkMinimalViewModel(seismic: seismic)
|
||||
|
||||
gradientView.image = .gradient(from: viewModel.colors.startColor, to: viewModel.colors.endColor, with: .init(origin: .zero, size: .init(width: 500, height: 1)))
|
||||
|
||||
placeLabel.text = viewModel.place
|
||||
placeLabel.textColor = isPushSelected ? AppTheme.Colors.pureBlue : AppTheme.shared.cardTextColor
|
||||
magnitudeLabel.textColor = viewModel.colors.textColor
|
||||
magnitudeLabel.text = viewModel.magnitude
|
||||
timeLabel.text = "🕗 \(viewModel.time)"
|
||||
distanceLabel.text = "📐 \(viewModel.distance)"
|
||||
|
||||
if !viewModel.smartphones.isEmpty {
|
||||
smartphonesLabel.text = "🚨 \(viewModel.smartphones)"
|
||||
}
|
||||
if !viewModel.users.isEmpty {
|
||||
alertsLabel.text = "⚠️ \(viewModel.users)"
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
/// Configure the cell to display a seismic
|
||||
/// - Parameters:
|
||||
/// - seismic: Seismic to display
|
||||
/// - type: Type of cell
|
||||
/// - informations: Informations to show
|
||||
public func configure(
|
||||
with seismic: EQNSisma,
|
||||
isPushSelected: Bool
|
||||
) {
|
||||
self.seismic = seismic
|
||||
self.isPushSelected = isPushSelected
|
||||
|
||||
if seismic.preliminary.intValue > 0 {
|
||||
informationTypes.insert(.preliminary)
|
||||
}
|
||||
if seismic.smartphoneNumber.intValue > 0 {
|
||||
informationTypes.insert(.realtimeSmartphones)
|
||||
}
|
||||
if seismic.userNumber.intValue > 0 {
|
||||
informationTypes.insert(.reportUsers)
|
||||
}
|
||||
if seismic.isoCode == "0" {
|
||||
informationTypes.remove(.intensityMap)
|
||||
}
|
||||
|
||||
recreateUI()
|
||||
updateUI()
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@objc private func intensityMapTapped(_ sender: Any) {
|
||||
delegate?.seismicNetworkCellDidTapIntensityMapDetail(self)
|
||||
}
|
||||
}
|
||||
+11
-96
@@ -11,32 +11,8 @@ import MapKit
|
||||
import CoreLocation
|
||||
import Shogun
|
||||
|
||||
protocol SeismicNetworkTableViewCellDelegate: AnyObject {
|
||||
func seismicNetworkCellDidTapShare(_ cell: SeismicNetworkTableViewCell)
|
||||
func seismicNetworkCellDidTapMap(_ cell: SeismicNetworkTableViewCell)
|
||||
func seismicNetworkCellDidTapMapDetail(_ cell: SeismicNetworkTableViewCell)
|
||||
func seismicNetworkCellDidTapIntensityMapDetail(_ cell: SeismicNetworkTableViewCell)
|
||||
func seismicNetworkCellDidTapCalendar(_ cell: SeismicNetworkTableViewCell)
|
||||
func seismicNetworkCellDidTapSettings(_ cell: SeismicNetworkTableViewCell)
|
||||
func seismicNetworkCellDidTapClose(_ cell: SeismicNetworkTableViewCell)
|
||||
}
|
||||
|
||||
class SeismicNetworkTableViewCell: UITableViewCell {
|
||||
|
||||
static let Identifier = "SeismicNetworkTableViewCell"
|
||||
|
||||
/// Available informations to display inside the cell
|
||||
enum InformationType: Int {
|
||||
case preliminary
|
||||
case time
|
||||
case distance
|
||||
case coordinate
|
||||
case population
|
||||
case realtimeSmartphones
|
||||
case reportUsers
|
||||
case intensityMap
|
||||
case buttons
|
||||
}
|
||||
class SeismicNetworkTableViewCell: SeismicNetworkBaseTableViewCell {
|
||||
|
||||
/// Available cell type
|
||||
enum DisplayType {
|
||||
@@ -45,15 +21,6 @@ class SeismicNetworkTableViewCell: UITableViewCell {
|
||||
/// Cell with map visible
|
||||
case mapExpanded
|
||||
}
|
||||
|
||||
/// Delegate
|
||||
weak var delegate: SeismicNetworkTableViewCellDelegate?
|
||||
|
||||
// MARK: - Internal
|
||||
|
||||
private static let DefaultButtonHeight: CGFloat = 34.0
|
||||
private static let VerticalSpacingDefault: CGFloat = 6.0
|
||||
private static let VerticalSpacingSmall: CGFloat = 2.0
|
||||
|
||||
/// Seismic to show
|
||||
private var seismic: EQNSisma?
|
||||
@@ -62,26 +29,7 @@ class SeismicNetworkTableViewCell: UITableViewCell {
|
||||
private var isPushSelected = false
|
||||
|
||||
// MARK: - UI Components
|
||||
|
||||
private lazy var containerView: UIView = {
|
||||
let view = UIView(frame: .zero)
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.backgroundColor = .white
|
||||
view.clipsToBounds = true
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var gradientView: UIImageView = {
|
||||
// Per gestire il gradiente, utilizziamo una image view in cui inseriamo un'immagine
|
||||
// creata ad-hoc con il gradiente desiderato.
|
||||
// Le prove fatte utilizzando una view normale sono fallite perchè al momento di
|
||||
// disegnare la view non abbiamo le misure corrette.
|
||||
let view = UIImageView(frame: .zero)
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.contentMode = .scaleToFill
|
||||
return view
|
||||
}()
|
||||
|
||||
|
||||
private lazy var placeLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
@@ -208,20 +156,9 @@ class SeismicNetworkTableViewCell: UITableViewCell {
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
private func setupUI() {
|
||||
selectionStyle = .default
|
||||
backgroundColor = .clear
|
||||
|
||||
// container view
|
||||
contentView.addSubview(containerView)
|
||||
containerView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 4.0).isActive = true
|
||||
containerView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8.0).isActive = true
|
||||
containerView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8.0).isActive = true
|
||||
containerView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -4.0).isActive = true
|
||||
override func setupUI() {
|
||||
super.setupUI()
|
||||
|
||||
containerView.addSubview(gradientView)
|
||||
gradientView.constraint(to: containerView)
|
||||
|
||||
// this variable is used to keep track of the previous view, in order to attach proper constraints
|
||||
var previousView: UIView = containerView
|
||||
|
||||
@@ -391,12 +328,6 @@ class SeismicNetworkTableViewCell: UITableViewCell {
|
||||
gradientView.eqn_applyRoundedCorners()
|
||||
}
|
||||
|
||||
private func recreateUI() {
|
||||
// remove all subviews and recreate the required components
|
||||
containerView.subviews.forEach({ $0.removeFromSuperview() })
|
||||
setupUI()
|
||||
}
|
||||
|
||||
private func updateUI() {
|
||||
guard let seismic = seismic else { return }
|
||||
|
||||
@@ -427,7 +358,6 @@ class SeismicNetworkTableViewCell: UITableViewCell {
|
||||
alertsLabel.text = "⚠️ \(viewModel.users)"
|
||||
}
|
||||
|
||||
|
||||
if displayType == .mapExpanded {
|
||||
// zoom based on population involved
|
||||
let longitudeSpan = mapSpanLongitude(population: seismic.population100km)
|
||||
@@ -488,52 +418,37 @@ class SeismicNetworkTableViewCell: UITableViewCell {
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@objc func shareTapped(_ sender: UIButton) {
|
||||
@objc private func shareTapped(_ sender: UIButton) {
|
||||
delegate?.seismicNetworkCellDidTapShare(self)
|
||||
}
|
||||
|
||||
@objc func mapTapped(_ sender: UIButton) {
|
||||
@objc private func mapTapped(_ sender: UIButton) {
|
||||
if displayType != .mapExpanded {
|
||||
delegate?.seismicNetworkCellDidTapMap(self)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func calendarTapped(_ sender: UIButton) {
|
||||
@objc private func calendarTapped(_ sender: UIButton) {
|
||||
delegate?.seismicNetworkCellDidTapCalendar(self)
|
||||
}
|
||||
|
||||
@objc func settingsTapped(_ sender: UIButton) {
|
||||
@objc private func settingsTapped(_ sender: UIButton) {
|
||||
delegate?.seismicNetworkCellDidTapSettings(self)
|
||||
}
|
||||
|
||||
@objc func closeTapped(_ sender: UIButton) {
|
||||
@objc private func closeTapped(_ sender: UIButton) {
|
||||
delegate?.seismicNetworkCellDidTapClose(self)
|
||||
}
|
||||
|
||||
@objc func mapDetailTapped(_ sender: Any) {
|
||||
@objc private func mapDetailTapped(_ sender: Any) {
|
||||
delegate?.seismicNetworkCellDidTapMapDetail(self)
|
||||
}
|
||||
|
||||
@objc func intensityMapTapped(_ sender: Any) {
|
||||
@objc private func intensityMapTapped(_ sender: Any) {
|
||||
delegate?.seismicNetworkCellDidTapIntensityMapDetail(self)
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
@discardableResult
|
||||
private func addSeparator(constraintTo: NSLayoutYAxisAnchor, constanst: CGFloat = 8.0) -> UIView {
|
||||
let separator = UIView()
|
||||
separator.translatesAutoresizingMaskIntoConstraints = false
|
||||
separator.backgroundColor = .lightGray
|
||||
containerView.addSubview(separator)
|
||||
|
||||
separator.topAnchor.constraint(equalTo: constraintTo, constant: constanst).isActive = true
|
||||
separator.leadingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.leadingAnchor).isActive = true
|
||||
separator.trailingAnchor.constraint(equalTo: containerView.layoutMarginsGuide.trailingAnchor).isActive = true
|
||||
separator.heightAnchor.constraint(equalToConstant: 1.0).isActive = true
|
||||
|
||||
return separator
|
||||
}
|
||||
|
||||
/// Determines the zoom for the map, based on the involved population
|
||||
private func mapSpanLongitude(population: Double) -> CLLocationDegrees {
|
||||
|
||||
+119
-80
@@ -8,21 +8,62 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
struct MagnitudeColors {
|
||||
let textColor: UIColor
|
||||
let startColor: UIColor
|
||||
let endColor: UIColor
|
||||
}
|
||||
|
||||
|
||||
struct SeismicNetworkMinimalViewModel {
|
||||
private let seismic: EQNSisma
|
||||
let place: String
|
||||
let isPreliminary: Bool
|
||||
let magnitude: String
|
||||
let time: String
|
||||
let distance: String
|
||||
let smartphones: String
|
||||
let users: String
|
||||
let colors: MagnitudeColors
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
init(seismic: EQNSisma) {
|
||||
self.seismic = seismic
|
||||
self.place = seismic.place
|
||||
let isPreliminary = seismic.preliminary.intValue > 0
|
||||
self.isPreliminary = isPreliminary
|
||||
self.magnitude = String(format: "%.1f", seismic.magnitude.doubleValue)
|
||||
|
||||
let time = EQNUtility.formattedString(forTimeDifference: Int(seismic.timeDifference))
|
||||
self.time = time
|
||||
|
||||
let distanceRounded = Int(round(seismic.userDistance))
|
||||
self.distance = "\(distanceRounded) km"
|
||||
|
||||
if seismic.smartphoneNumber.intValue > 0 {
|
||||
self.smartphones = String(format: NSLocalizedString("official_smartphones", comment: ""), seismic.smartphoneNumber)
|
||||
} else {
|
||||
self.smartphones = ""
|
||||
}
|
||||
if seismic.userNumber.intValue > 0 {
|
||||
self.users = String(format: NSLocalizedString("official_reports", comment: ""), seismic.userNumber)
|
||||
} else {
|
||||
self.users = ""
|
||||
}
|
||||
|
||||
self.colors = calculateColors(for: seismic.magnitude.doubleValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct SeismicNetworkViewModel {
|
||||
|
||||
struct MagnitudeColors {
|
||||
let textColor: UIColor
|
||||
let startColor: UIColor
|
||||
let endColor: UIColor
|
||||
}
|
||||
|
||||
private let seismic: EQNSisma
|
||||
let place: String
|
||||
let network: String
|
||||
let isPreliminary: Bool
|
||||
let magnitude: String
|
||||
let rawMagnitude: Double
|
||||
let depth: String
|
||||
let time: String
|
||||
let distance: String
|
||||
@@ -38,7 +79,6 @@ struct SeismicNetworkViewModel {
|
||||
self.seismic = seismic
|
||||
self.place = seismic.place
|
||||
self.network = seismic.provider
|
||||
self.rawMagnitude = seismic.magnitude.doubleValue
|
||||
|
||||
let isPreliminary = seismic.preliminary.intValue > 0
|
||||
self.isPreliminary = isPreliminary
|
||||
@@ -67,7 +107,7 @@ struct SeismicNetworkViewModel {
|
||||
let coordinateText = EQNUtility.coordinateString(coordinate: seismic.coordinate.coordinate)
|
||||
self.coordinate = "\(coordinateText)"
|
||||
|
||||
let population = Self.formatPopulation(seismic.population100km)
|
||||
let population = formatPopulation(seismic.population100km)
|
||||
self.population = String(format: NSLocalizedString("share_radius100", comment: ""), population)
|
||||
|
||||
if seismic.smartphoneNumber.intValue > 0 {
|
||||
@@ -81,78 +121,8 @@ struct SeismicNetworkViewModel {
|
||||
self.users = ""
|
||||
}
|
||||
|
||||
self.colors = Self.calculateColors(for: seismic.magnitude.doubleValue)
|
||||
self.colors = calculateColors(for: seismic.magnitude.doubleValue)
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
/// Format population value (ex. 1.5M, 2.4k)
|
||||
private static func formatPopulation(_ population: Double) -> String {
|
||||
var populationString = ""
|
||||
if population > 999_999 {
|
||||
let roundedPopulation = round(population / 100_000) / 10
|
||||
populationString = "\(roundedPopulation)M"
|
||||
} else if population > 999 {
|
||||
let roundedPopulation = round(population / 100) / 10
|
||||
populationString = "\(roundedPopulation)K"
|
||||
} else {
|
||||
let roundedPopulation = round(population)
|
||||
populationString = "\(roundedPopulation)"
|
||||
}
|
||||
return populationString
|
||||
}
|
||||
|
||||
/// Calculate colors to use for text and background of the cell
|
||||
private static func calculateColors(for magnitude: Double) -> MagnitudeColors {
|
||||
var textColor = UIColor.black
|
||||
|
||||
var r = 0, g = 0, b = 0
|
||||
if (magnitude < 2.0) {
|
||||
let fraction: Double = 1 - (magnitude - 0.0) / (2.0 - 0.0)
|
||||
r = Int(round(200.0 + (255.0 - 200.0) * fraction))
|
||||
g = Int(round(226.0 + (255.0 - 226.0) * fraction))
|
||||
b = Int(round(196.0 + (255.0 - 196.0) * fraction))
|
||||
textColor = UIColor(red: 12.0 / 255.0, green: 115.0 / 255.0, blue: 160.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
if (magnitude >= 2.0 && magnitude < 3.5) {
|
||||
let fraction: Double = 1 - (magnitude - 2) / (3.5 - 2)
|
||||
r = Int(round(136.0 + (200.0 - 136.0) * fraction))
|
||||
g = Int(round(175.0 + (226.0 - 175.0) * fraction))
|
||||
b = Int(round(131.0 + (196.0 - 131.0) * fraction))
|
||||
textColor = UIColor(red: 12.0 / 255.0, green: 160.0 / 255.0, blue: 35.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
if (magnitude >= 3.5 && magnitude < 4.5) {
|
||||
let fraction: Double = 1 - (magnitude - 3.5) / (4.5 - 3.5)
|
||||
r = 252
|
||||
g = Int(round(233.0 + (253.0 - 233.0) * fraction))
|
||||
b = Int(round(179.0 + (209.0 - 179.0) * fraction))
|
||||
textColor = UIColor(red: 244.0 / 255.0, green: 195.0 / 255.0, blue: 0.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
if (magnitude >= 4.5 && magnitude < 5.5) {
|
||||
let fraction: Double = 1 - (magnitude - 4.5) / (5.5 - 4.5)
|
||||
r = 252
|
||||
g = Int(round(159.0 + (197.0 - 159.0) * fraction))
|
||||
b = Int(round(161.0 + (197.0 - 161.0) * fraction))
|
||||
textColor = UIColor(red: 255.0 / 255.0, green: 0.0 / 255.0, blue: 0.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
if (magnitude >= 5.5) {
|
||||
let fraction: Double = 1 - (magnitude - 5.5) / (10 - 5.5)
|
||||
r = Int(round(190.0 + (254.0 - 190.0) * fraction))
|
||||
g = Int(round(124.0 + (219.0 - 124.0) * fraction))
|
||||
b = 255
|
||||
textColor = UIColor(red: 183.0 / 255.0, green: 60.0 / 255.0, blue: 252.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
|
||||
let r2 = min(r + 30, 255)
|
||||
let g2 = min(g + 30, 255)
|
||||
let b2 = min(b + 30, 255)
|
||||
|
||||
let startColor = UIColor(red: CGFloat(r) / 255.0, green: CGFloat(g) / 255.0, blue: CGFloat(b) / 255.0, alpha: 1.0)
|
||||
let endColor = UIColor(red: CGFloat(r2) / 255.0, green: CGFloat(g2) / 255.0, blue: CGFloat(b2) / 255.0, alpha: 1.0)
|
||||
|
||||
return .init(textColor: textColor, startColor: startColor, endColor: endColor)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension SeismicNetworkViewModel: Equatable {
|
||||
@@ -160,3 +130,72 @@ extension SeismicNetworkViewModel: Equatable {
|
||||
return lhs.seismic == rhs.seismic
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
/// Calculate colors to use for text and background of the cell
|
||||
private func calculateColors(for magnitude: Double) -> MagnitudeColors {
|
||||
var textColor = UIColor.black
|
||||
|
||||
var r = 0, g = 0, b = 0
|
||||
if (magnitude < 2.0) {
|
||||
let fraction: Double = 1 - (magnitude - 0.0) / (2.0 - 0.0)
|
||||
r = Int(round(200.0 + (255.0 - 200.0) * fraction))
|
||||
g = Int(round(226.0 + (255.0 - 226.0) * fraction))
|
||||
b = Int(round(196.0 + (255.0 - 196.0) * fraction))
|
||||
textColor = UIColor(red: 12.0 / 255.0, green: 115.0 / 255.0, blue: 160.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
if (magnitude >= 2.0 && magnitude < 3.5) {
|
||||
let fraction: Double = 1 - (magnitude - 2) / (3.5 - 2)
|
||||
r = Int(round(136.0 + (200.0 - 136.0) * fraction))
|
||||
g = Int(round(175.0 + (226.0 - 175.0) * fraction))
|
||||
b = Int(round(131.0 + (196.0 - 131.0) * fraction))
|
||||
textColor = UIColor(red: 12.0 / 255.0, green: 160.0 / 255.0, blue: 35.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
if (magnitude >= 3.5 && magnitude < 4.5) {
|
||||
let fraction: Double = 1 - (magnitude - 3.5) / (4.5 - 3.5)
|
||||
r = 252
|
||||
g = Int(round(233.0 + (253.0 - 233.0) * fraction))
|
||||
b = Int(round(179.0 + (209.0 - 179.0) * fraction))
|
||||
textColor = UIColor(red: 244.0 / 255.0, green: 195.0 / 255.0, blue: 0.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
if (magnitude >= 4.5 && magnitude < 5.5) {
|
||||
let fraction: Double = 1 - (magnitude - 4.5) / (5.5 - 4.5)
|
||||
r = 252
|
||||
g = Int(round(159.0 + (197.0 - 159.0) * fraction))
|
||||
b = Int(round(161.0 + (197.0 - 161.0) * fraction))
|
||||
textColor = UIColor(red: 255.0 / 255.0, green: 0.0 / 255.0, blue: 0.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
if (magnitude >= 5.5) {
|
||||
let fraction: Double = 1 - (magnitude - 5.5) / (10 - 5.5)
|
||||
r = Int(round(190.0 + (254.0 - 190.0) * fraction))
|
||||
g = Int(round(124.0 + (219.0 - 124.0) * fraction))
|
||||
b = 255
|
||||
textColor = UIColor(red: 183.0 / 255.0, green: 60.0 / 255.0, blue: 252.0 / 255.0, alpha: 1.0)
|
||||
}
|
||||
|
||||
let r2 = min(r + 30, 255)
|
||||
let g2 = min(g + 30, 255)
|
||||
let b2 = min(b + 30, 255)
|
||||
|
||||
let startColor = UIColor(red: CGFloat(r) / 255.0, green: CGFloat(g) / 255.0, blue: CGFloat(b) / 255.0, alpha: 1.0)
|
||||
let endColor = UIColor(red: CGFloat(r2) / 255.0, green: CGFloat(g2) / 255.0, blue: CGFloat(b2) / 255.0, alpha: 1.0)
|
||||
|
||||
return .init(textColor: textColor, startColor: startColor, endColor: endColor)
|
||||
}
|
||||
|
||||
/// Format population value (ex. 1.5M, 2.4k)
|
||||
private func formatPopulation(_ population: Double) -> String {
|
||||
var populationString = ""
|
||||
if population > 999_999 {
|
||||
let roundedPopulation = round(population / 100_000) / 10
|
||||
populationString = "\(roundedPopulation)M"
|
||||
} else if population > 999 {
|
||||
let roundedPopulation = round(population / 100) / 10
|
||||
populationString = "\(roundedPopulation)K"
|
||||
} else {
|
||||
let roundedPopulation = round(population)
|
||||
populationString = "\(roundedPopulation)"
|
||||
}
|
||||
return populationString
|
||||
}
|
||||
|
||||
+53
-25
@@ -18,6 +18,12 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
case advertise(NativeAd)
|
||||
}
|
||||
|
||||
enum CardDisplayType: Int, CaseIterable {
|
||||
case small
|
||||
case full
|
||||
case minimal
|
||||
}
|
||||
|
||||
private static let SegueIdentifierFilters = "ShowFilters"
|
||||
private static let SegueIdentifierCardSettings = "ShowCardSettings"
|
||||
|
||||
@@ -34,6 +40,11 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
|
||||
/// Cells to display (must be seismics or ad banners)
|
||||
private var rows = [CellType]()
|
||||
/// Type of cards to show
|
||||
private var cardDisplayType: CardDisplayType {
|
||||
get { AppPreferences.shared.seismicNetworksCardStyle }
|
||||
set { AppPreferences.shared.seismicNetworksCardStyle = newValue }
|
||||
}
|
||||
private var seismicViewModels = [SeismicNetworkViewModel]()
|
||||
/// Informations to display on a single cell
|
||||
private var informations: [SeismicNetworkTableViewCell.InformationType] {
|
||||
@@ -56,7 +67,7 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
|
||||
// MARK: - UI
|
||||
|
||||
@IBOutlet private weak var expandeCollapseButton: UIBarButtonItem!
|
||||
@IBOutlet private weak var displayModeButton: UIBarButtonItem!
|
||||
@IBOutlet private weak var sortButton: UIBarButtonItem!
|
||||
private var tableViewTopConstraint: NSLayoutConstraint?
|
||||
|
||||
@@ -185,6 +196,7 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
tableView.estimatedRowHeight = 300.0
|
||||
tableView.rowHeight = UITableView.automaticDimension
|
||||
tableView.registerCell(for: SeismicNetworkTableViewCell.self)
|
||||
tableView.registerCell(for: SeismicNetworkMinimalTableViewCell.self)
|
||||
tableView.registerCell(for: SeismicNetworkAdvertiseTableViewCell.self)
|
||||
tableView.emptyDataSetSource = self
|
||||
tableView.separatorStyle = .none
|
||||
@@ -263,10 +275,13 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
private func refreshUI() {
|
||||
elaborateData()
|
||||
|
||||
if informations.contains(.buttons) {
|
||||
expandeCollapseButton.image = UIImage(named: "navbar-icon-arrow-collapse")
|
||||
} else {
|
||||
expandeCollapseButton.image = UIImage(named: "navbar-icon-arrow-expand")
|
||||
switch cardDisplayType {
|
||||
case .small:
|
||||
displayModeButton.image = UIImage(systemName: "1.square")
|
||||
case .full:
|
||||
displayModeButton.image = UIImage(systemName: "2.square")
|
||||
case .minimal:
|
||||
displayModeButton.image = UIImage(systemName: "3.square")
|
||||
}
|
||||
|
||||
tableView.reloadData()
|
||||
@@ -631,10 +646,15 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
}
|
||||
|
||||
@IBAction func collapseExpandTapped(_ sender: Any) {
|
||||
if informations.contains(.buttons) {
|
||||
cardDisplayType.next()
|
||||
|
||||
switch cardDisplayType {
|
||||
case .small:
|
||||
informations.removeAll(where: { $0 == .buttons })
|
||||
} else {
|
||||
case .full:
|
||||
informations.append(.buttons)
|
||||
case .minimal:
|
||||
break
|
||||
}
|
||||
|
||||
refreshUI()
|
||||
@@ -650,17 +670,25 @@ class SeismicNetworksViewController: UIViewController, UITableViewDelegate, UITa
|
||||
let row = rows[indexPath.row]
|
||||
switch row {
|
||||
case .seismic(let seismic):
|
||||
let cell = tableView.dequeueReusableCell(cellIdentifiable: SeismicNetworkTableViewCell.self, for: indexPath)
|
||||
|
||||
var type = SeismicNetworkTableViewCell.DisplayType.normal
|
||||
if openMapIndexPath == indexPath {
|
||||
type = .mapExpanded
|
||||
switch cardDisplayType {
|
||||
case .small, .full:
|
||||
let cell = tableView.dequeueReusableCell(cellIdentifiable: SeismicNetworkTableViewCell.self, for: indexPath)
|
||||
|
||||
var type = SeismicNetworkTableViewCell.DisplayType.normal
|
||||
if openMapIndexPath == indexPath {
|
||||
type = .mapExpanded
|
||||
}
|
||||
|
||||
let isPushSelected = isSeismicToHighlight(seismic: seismic)
|
||||
cell.configure(with: seismic, type: type, informations: informations, isPushSelected: isPushSelected)
|
||||
cell.delegate = self
|
||||
return cell
|
||||
case .minimal:
|
||||
let cell = tableView.dequeueReusableCell(cellIdentifiable: SeismicNetworkMinimalTableViewCell.self, for: indexPath)
|
||||
let isPushSelected = isSeismicToHighlight(seismic: seismic)
|
||||
cell.configure(with: seismic, isPushSelected: isPushSelected)
|
||||
return cell
|
||||
}
|
||||
|
||||
let isPushSelected = isSeismicToHighlight(seismic: seismic)
|
||||
cell.configure(with: seismic, type: type, informations: informations, isPushSelected: isPushSelected)
|
||||
cell.delegate = self
|
||||
return cell
|
||||
case .advertise(let nativeAd):
|
||||
let cell = tableView.dequeueReusableCell(cellIdentifiable: SeismicNetworkAdvertiseTableViewCell.self, for: indexPath)
|
||||
cell.loadNativeAd(nativeAd)
|
||||
@@ -753,9 +781,9 @@ extension SeismicNetworksViewController: NativeAdLoaderDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
extension SeismicNetworksViewController: SeismicNetworkTableViewCellDelegate {
|
||||
extension SeismicNetworksViewController: SeismicNetworkBaseTableViewCellDelegate {
|
||||
|
||||
func seismicNetworkCellDidTapShare(_ cell: SeismicNetworkTableViewCell) {
|
||||
func seismicNetworkCellDidTapShare(_ cell: SeismicNetworkBaseTableViewCell) {
|
||||
guard let index = tableView.indexPath(for: cell), case let .seismic(seismic) = rows[index.row] else { return }
|
||||
|
||||
// create a snapshot of the cell and share with default share sheet
|
||||
@@ -772,7 +800,7 @@ extension SeismicNetworksViewController: SeismicNetworkTableViewCellDelegate {
|
||||
present(controller, animated: true)
|
||||
}
|
||||
|
||||
func seismicNetworkCellDidTapMap(_ cell: SeismicNetworkTableViewCell) {
|
||||
func seismicNetworkCellDidTapMap(_ cell: SeismicNetworkBaseTableViewCell) {
|
||||
guard let index = tableView.indexPath(for: cell) else { return }
|
||||
|
||||
let indexToReloads = [openMapIndexPath, index].compactMap { $0 }
|
||||
@@ -781,29 +809,29 @@ extension SeismicNetworksViewController: SeismicNetworkTableViewCellDelegate {
|
||||
tableView.reloadRows(at: indexToReloads, with: .automatic)
|
||||
}
|
||||
|
||||
func seismicNetworkCellDidTapMapDetail(_ cell: SeismicNetworkTableViewCell) {
|
||||
func seismicNetworkCellDidTapMapDetail(_ cell: SeismicNetworkBaseTableViewCell) {
|
||||
guard let index = tableView.indexPath(for: cell), case let .seismic(seismic) = rows[index.row] else { return }
|
||||
|
||||
showMapDetail(for: seismic)
|
||||
}
|
||||
|
||||
func seismicNetworkCellDidTapIntensityMapDetail(_ cell: SeismicNetworkTableViewCell) {
|
||||
func seismicNetworkCellDidTapIntensityMapDetail(_ cell: SeismicNetworkBaseTableViewCell) {
|
||||
guard let index = tableView.indexPath(for: cell), case let .seismic(seismic) = rows[index.row] else { return }
|
||||
|
||||
showIntensityMap(for: seismic)
|
||||
}
|
||||
|
||||
func seismicNetworkCellDidTapCalendar(_ cell: SeismicNetworkTableViewCell) {
|
||||
func seismicNetworkCellDidTapCalendar(_ cell: SeismicNetworkBaseTableViewCell) {
|
||||
guard let index = tableView.indexPath(for: cell), case let .seismic(seismic) = rows[index.row] else { return }
|
||||
|
||||
openCalendar(for: seismic)
|
||||
}
|
||||
|
||||
func seismicNetworkCellDidTapSettings(_ cell: SeismicNetworkTableViewCell) {
|
||||
func seismicNetworkCellDidTapSettings(_ cell: SeismicNetworkBaseTableViewCell) {
|
||||
performSegue(withIdentifier: Self.SegueIdentifierCardSettings, sender: nil)
|
||||
}
|
||||
|
||||
func seismicNetworkCellDidTapClose(_ cell: SeismicNetworkTableViewCell) {
|
||||
func seismicNetworkCellDidTapClose(_ cell: SeismicNetworkBaseTableViewCell) {
|
||||
guard let index = tableView.indexPath(for: cell) else { return }
|
||||
|
||||
let indexToReloads = [openMapIndexPath, index].compactMap { $0 }
|
||||
|
||||
@@ -37,3 +37,13 @@ extension CGFloat {
|
||||
self*2.0
|
||||
}
|
||||
}
|
||||
|
||||
extension CaseIterable where Self: Equatable {
|
||||
mutating func next() {
|
||||
let all = Self.allCases
|
||||
let idx = all.firstIndex(of: self)!
|
||||
let next = all.index(after: idx)
|
||||
let newValue = all[next == all.endIndex ? all.startIndex : next]
|
||||
self = newValue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,4 +52,14 @@ class AppPreferences: NSObject {
|
||||
UserDefaults.standard.set(newValue.map { $0.rawValue }, forKey: UserDefaults.SeismicNetworksCardInformations)
|
||||
}
|
||||
}
|
||||
|
||||
var seismicNetworksCardStyle: SeismicNetworksViewController.CardDisplayType {
|
||||
get {
|
||||
let saved = UserDefaults.standard.integer(forKey: UserDefaults.SeismicNetworksCardStyle)
|
||||
return SeismicNetworksViewController.CardDisplayType(rawValue: saved) ?? .small
|
||||
}
|
||||
set {
|
||||
UserDefaults.standard.set(newValue.rawValue, forKey: UserDefaults.SeismicNetworksCardStyle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +114,9 @@ public class EQNUserDefaultsCommand: EQNCommandProtocol {
|
||||
}
|
||||
AppPreferences.shared.seismicNetworksInformations = informations
|
||||
|
||||
let cardDisplayType: SeismicNetworksViewController.CardDisplayType = informations.contains(.buttons) ? .full : .small
|
||||
AppPreferences.shared.seismicNetworksCardStyle = cardDisplayType
|
||||
|
||||
userDefaults.set(true, forKey: UserDefaults.AppMigrationV5_9)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,4 @@ enum MapPinStyle: Int, CaseIterable {
|
||||
case circle
|
||||
case light
|
||||
case full
|
||||
|
||||
mutating func next() {
|
||||
let all = Self.allCases
|
||||
let idx = all.firstIndex(of: self)!
|
||||
let next = all.index(after: idx)
|
||||
let newValue = all[next == all.endIndex ? all.startIndex : next]
|
||||
self = newValue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="6kD-jk-5Aw">
|
||||
<rightBarButtonItems>
|
||||
<barButtonItem image="navbar-icon-refresh" id="ZJh-jF-ILm">
|
||||
<barButtonItem image="1.square" catalog="system" id="HTN-07-s5p">
|
||||
<connections>
|
||||
<action selector="refreshDataTapped:" destination="tVM-DH-fmv" id="qs5-jS-0Op"/>
|
||||
<action selector="collapseExpandTapped:" destination="tVM-DH-fmv" id="EnD-92-5ZX"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
<barButtonItem image="navbar-icon-filters" id="vOM-Np-CIk">
|
||||
@@ -32,15 +32,15 @@
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
<barButtonItem image="navbar-icon-sort" id="LyU-KI-3Mb"/>
|
||||
<barButtonItem image="navbar-icon-arrow-collapse" id="HTN-07-s5p">
|
||||
<barButtonItem image="navbar-icon-refresh" id="ZJh-jF-ILm">
|
||||
<connections>
|
||||
<action selector="collapseExpandTapped:" destination="tVM-DH-fmv" id="EnD-92-5ZX"/>
|
||||
<action selector="refreshDataTapped:" destination="tVM-DH-fmv" id="qs5-jS-0Op"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</rightBarButtonItems>
|
||||
</navigationItem>
|
||||
<connections>
|
||||
<outlet property="expandeCollapseButton" destination="HTN-07-s5p" id="lxP-Im-NME"/>
|
||||
<outlet property="displayModeButton" destination="HTN-07-s5p" id="Lhc-Od-MvL"/>
|
||||
<outlet property="sortButton" destination="LyU-KI-3Mb" id="969-Zg-YBB"/>
|
||||
<segue destination="6LP-zk-O1z" kind="presentation" identifier="ShowFilters" modalPresentationStyle="overCurrentContext" modalTransitionStyle="crossDissolve" id="Nzu-iH-UgB"/>
|
||||
<segue destination="Rfp-kt-2Kx" kind="presentation" identifier="ShowCardSettings" modalPresentationStyle="overCurrentContext" modalTransitionStyle="crossDissolve" id="VWw-16-xGw"/>
|
||||
@@ -621,6 +621,7 @@
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="1.square" catalog="system" width="128" height="114"/>
|
||||
<image name="navbar-icon-arrow-collapse" width="24" height="24"/>
|
||||
<image name="navbar-icon-filters" width="24" height="24"/>
|
||||
<image name="navbar-icon-refresh" width="24" height="24"/>
|
||||
|
||||
Reference in New Issue
Block a user