Commit 38c8f007 by Dmitriy Stepanets

RadarViewController: Added layers action

parent 2764ea06
No preview for this file type
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<key>1Weather.xcscheme_^#shared#^_</key> <key>1Weather.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>24</integer> <integer>11</integer>
</dict> </dict>
<key>PG (Playground) 1.xcscheme</key> <key>PG (Playground) 1.xcscheme</key>
<dict> <dict>
......
// //
// WeatherLayer.swift // RadarLayer.swift
// 1Weather // 1Weather
// //
// Created by Dmitry Stepanets on 16.04.2021. // Created by Dmitry Stepanets on 16.04.2021.
...@@ -7,9 +7,7 @@ ...@@ -7,9 +7,7 @@
import UIKit import UIKit
struct WeatherLayer { struct RadarLayer {
var pinned:Bool var pinned = false
var name:String let layer:RadarLayerType
var legendColors:[CGColor]
var values:[String]
} }
//
// RadarLayerProtocol.swift
// 1Weather
//
// Created by Dmitry Stepanets on 19.04.2021.
//
import UIKit
protocol RadarLayerType {
var id:String { get }
var name:String { get }
var values:[String] { get }
var colors:[CGColor] { get }
}
//
// SevereLayerType.swift
// 1Weather
//
// Created by Dmitry Stepanets on 19.04.2021.
//
import UIKit
public enum SevereLayerType:String, CaseIterable, RadarLayerType {
case fire = "radar.severeLayer.fire"
case floods = "radar.severeLayer.floods"
case fog = "radar.severeLayer.fog"
case freezing = "radar.severeLayer.freezing"
case hurricaneTropical = "radar.severeLayer.hurricaneTropical"
case hurricaneTropicalTracks = "radar.severeLayer.hurricaneTropicalTracks"
case ice = "radar.severeLayer.ice"
case snow = "radar.severeLayer.snow"
case stormTornados = "radar.severeLayer.stormTornados"
case wind = "radar.severeLayer.wind"
case winter = "radar.severeLayer.winter"
var id:String {
return self.rawValue
}
var name:String {
return self.rawValue.localized()
}
var values:[String] {
switch self {
case .fire:
return ["Watch", "Warning"]
case .floods:
return ["Flash warn.", "Flash watch", "Flood warn."]
case .fog:
return ["Freezing adv." , "Dense adv."]
case .freezing:
return ["Freezing warn.", "Frost adv.", "Frost warn."]
case .hurricaneTropical:
return ["Warning", "Watch", "Tropical warn.", "Tropical watch"]
case .hurricaneTropicalTracks:
return ["Forecast track", "Past track", "Forecast cone", "Hurricane", "Tropical storm", "Low", "Invest area"]
case .ice:
return ["Strom warn.", "Storm watch", "Sleet warn.", "Sleet adv.", "Freezing rain adv."]
case .snow:
return ["Heavy snow warn.", "Snow adv.", "Blowing snow warn.", "Blowing snow adv."]
case .stormTornados:
return ["Tornado warn.", "Tornado watch", "Severe T-Storm warn.", "Severe T-storm watch"]
case .wind:
return ["High wind warn.", "High wind adv.", "High wind watch", "Wind adv.", "Dust strom warn.", "Blowing dust adv."]
case .winter:
return ["Blizzard warn.", "Blizzard watch", "Winter strom warn.", "Winter storm watch", "Winter weather adv."]
}
}
var colors:[CGColor] {
return [UIColor.blue, UIColor.yellow].map{$0.cgColor}
}
}
// //
// WeatherLayers.swift // WeatherLayerType.swift
// 1Weather // 1Weather
// //
// Created by Dmitry Stepanets on 16.04.2021. // Created by Dmitry Stepanets on 19.04.2021.
// //
import UIKit import UIKit
private enum WeatherLayerType:CaseIterable { public enum WeatherLayerType:String, CaseIterable, RadarLayerType {
case radar case radar = "radar.weatherLayer.radar"
case clouds case clouds = "radar.weatherLayer.clouds"
case surfaceTemp case surfaceTemp = "radar.weatherLayer.surfaceTemp"
case dewPoint case dewPoint = "radar.weatherLayer.dewPoint"
case relativeHumidity case relativeHumidity = "radar.weatherLayer.relativeHumidity"
case windSpeed case windSpeed = "radar.weatherLayer.windSpeed"
case uvIndex case uvIndex = "radar.weatherLayer.uvIndex"
var id:String {
return self.rawValue
}
var name:String { var name:String {
switch self { return self.rawValue.localized()
case .radar:
return "radar.weatherLayer.radar".localized()
case .clouds:
return "radar.weatherLayer.clouds".localized()
case .surfaceTemp:
return "radar.weatherLayer.surfaceTemp".localized()
case .dewPoint:
return "radar.weatherLayer.dewPoint".localized()
case .relativeHumidity:
return "radar.weatherLayer.relativeHumidity".localized()
case .windSpeed:
return "radar.weatherLayer.windSpeed".localized()
case .uvIndex:
return "radar.weatherLayer.uvIndex".localized()
}
} }
var values:[String] { var values:[String] {
...@@ -110,30 +99,3 @@ private enum WeatherLayerType:CaseIterable { ...@@ -110,30 +99,3 @@ private enum WeatherLayerType:CaseIterable {
} }
} }
} }
struct WeatherLayers {
static var allLayers:[WeatherLayer] {
return WeatherLayerType.allCases.map{ WeatherLayer(pinned: false,
name: $0.name,
legendColors: $0.colors,
values: $0.values) }
}
}
private enum SevereLayerType:CaseIterable {
case fire
case floods
case fog
case freezing
case hurricaneTropical
case hurricaneTropicalTracks
case ice
case snow
case stormTornados
case wind
case winter
}
struct SevereLayers {
}
...@@ -8,63 +8,6 @@ ...@@ -8,63 +8,6 @@
import UIKit import UIKit
import Localize_Swift import Localize_Swift
@propertyWrapper
struct UserDefaultsUnitValue<T> {
var wrappedValue: T {
get {
guard
let data = UserDefaults.standard.data(forKey: key),
let decoded = NSKeyedUnarchiver.unarchiveObject(with: data) as? T
else {
return defaultValue
}
return decoded
}
set {
let data = NSKeyedArchiver.archivedData(withRootObject: newValue)
UserDefaults.standard.set(data, forKey: key)
UserDefaults.standard.synchronize()
Settings.shared.delegate.invoke { (delegate) in
delegate.settingsDidChange()
}
}
}
private let key: String
private let defaultValue: T
init(wrappedValue defaultValue:T, key:String) {
self.defaultValue = defaultValue
self.key = key
}
}
@propertyWrapper
struct UserDefaultsBasicValue<T> {
var wrappedValue: T {
get {
let value = UserDefaults.standard.value(forKey: key) as? T
return value ?? defaultValue
}
set {
UserDefaults.standard.setValue(newValue, forKey: key)
UserDefaults.standard.synchronize()
}
}
private let key: String
private let defaultValue: T
init(wrappedValue defaultValue:T, key:String) {
self.defaultValue = defaultValue
self.key = key
}
}
protocol SettingsDelegate:class { protocol SettingsDelegate:class {
func settingsDidChange() func settingsDidChange()
} }
...@@ -116,4 +59,10 @@ class Settings { ...@@ -116,4 +59,10 @@ class Settings {
public var locale:Locale { public var locale:Locale {
return Locale(identifier: Localize.currentLanguage()) return Locale(identifier: Localize.currentLanguage())
} }
@UserDefaultsBasicValue(key: "pinnedLayers")
public var pinnedLayerIds:[String] = []
@UserDefaultsBasicValue(key: "selectedLayer")
public var selectedLayerId:String = WeatherLayerType.radar.rawValue
} }
...@@ -121,6 +121,7 @@ ...@@ -121,6 +121,7 @@
//Radar //Radar
"radar.layers.base" = "Base layer"; "radar.layers.base" = "Base layer";
"radar.layers.severe" = "Severe weather layer"; "radar.layers.severe" = "Severe weather layer";
"radar.weatherLayer.radar" = "Radar"; "radar.weatherLayer.radar" = "Radar";
"radar.weatherLayer.clouds" = "Clouds"; "radar.weatherLayer.clouds" = "Clouds";
"radar.weatherLayer.surfaceTemp" = "Surface Temperature"; "radar.weatherLayer.surfaceTemp" = "Surface Temperature";
...@@ -129,6 +130,19 @@ ...@@ -129,6 +130,19 @@
"radar.weatherLayer.windSpeed" = "Wind Speed"; "radar.weatherLayer.windSpeed" = "Wind Speed";
"radar.weatherLayer.uvIndex" = "UV Index"; "radar.weatherLayer.uvIndex" = "UV Index";
"radar.severeLayer.fire" = "Fire";
"radar.severeLayer.floods" = "Floods";
"radar.severeLayer.fog" = "Fog";
"radar.severeLayer.freezing" = "Freezing";
"radar.severeLayer.hurricaneTropical" = "Hurricane and tropical";
"radar.severeLayer.hurricaneTropicalTracks" = "Hurricane and tropical tracks";
"radar.severeLayer.ice" = "Ice";
"radar.severeLayer.snow" = "Snow";
"radar.severeLayer.stormTornados" = "Strorm and tornados";
"radar.severeLayer.wind" = "Wind";
"radar.severeLayer.winter" = "Winter";
//Menu //Menu
"menu.goPremium" = "Go premium"; "menu.goPremium" = "Go premium";
"menu.premium.desc" = "Experience app without ads @ $8.99 a year"; "menu.premium.desc" = "Experience app without ads @ $8.99 a year";
......
//
// UserDefaultsWrapper.swift
// 1Weather
//
// Created by Dmitry Stepanets on 19.04.2021.
//
import Foundation
@propertyWrapper
struct UserDefaultsUnitValue<T> {
var wrappedValue: T {
get {
guard
let data = UserDefaults.standard.data(forKey: key),
let decoded = NSKeyedUnarchiver.unarchiveObject(with: data) as? T
else {
return defaultValue
}
return decoded
}
set {
let data = NSKeyedArchiver.archivedData(withRootObject: newValue)
UserDefaults.standard.set(data, forKey: key)
UserDefaults.standard.synchronize()
Settings.shared.delegate.invoke { (delegate) in
delegate.settingsDidChange()
}
}
}
private let key: String
private let defaultValue: T
init(wrappedValue defaultValue:T, key:String) {
self.defaultValue = defaultValue
self.key = key
}
}
@propertyWrapper
struct UserDefaultsBasicValue<T> {
var wrappedValue: T {
get {
let value = UserDefaults.standard.value(forKey: key) as? T
return value ?? defaultValue
}
set {
UserDefaults.standard.setValue(newValue, forKey: key)
UserDefaults.standard.synchronize()
}
}
private let key: String
private let defaultValue: T
init(wrappedValue defaultValue:T, key:String) {
self.defaultValue = defaultValue
self.key = key
}
}
...@@ -7,10 +7,18 @@ ...@@ -7,10 +7,18 @@
import UIKit import UIKit
protocol RadarLayerCellDelegate:class {
func cellPinButtonTouched(atLayer:RadarLayer)
}
class RadarLayerCell: UITableViewCell { class RadarLayerCell: UITableViewCell {
//Private //Private
private let nameLabel = UILabel() private let nameLabel = UILabel()
private let pinButton = UIButton() private let pinButton = UIButton()
private var currentRadarLayer:RadarLayer?
//Public
weak var delegate:RadarLayerCellDelegate?
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier) super.init(style: style, reuseIdentifier: reuseIdentifier)
...@@ -21,12 +29,23 @@ class RadarLayerCell: UITableViewCell { ...@@ -21,12 +29,23 @@ class RadarLayerCell: UITableViewCell {
updateUI() updateUI()
} }
override var isSelected: Bool {
didSet {
contentView.backgroundColor = isSelected ? ThemeManager.currentTheme.graphTintColor.withAlphaComponent(0.2) :
ThemeManager.currentTheme.baseBackgroundColor
}
}
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
public func configure(weatherLayer:WeatherLayer) { public func configure(radarLayer:RadarLayer) {
nameLabel.text = weatherLayer.name self.currentRadarLayer = radarLayer
nameLabel.text = radarLayer.layer.name
nameLabel.font = radarLayer.pinned ? AppFont.SFPro.bold(size: 14) : AppFont.SFPro.regular(size: 14)
pinButton.backgroundColor = radarLayer.pinned ? UIColor.black : UIColor(hex: 0x242B2E).withAlphaComponent(0.57)
pinButton.tintColor = radarLayer.pinned ? UIColor.white : UIColor(hex: 0xD9D9D9)
} }
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
...@@ -44,7 +63,11 @@ class RadarLayerCell: UITableViewCell { ...@@ -44,7 +63,11 @@ class RadarLayerCell: UITableViewCell {
} }
@objc private func handlePinButton() { @objc private func handlePinButton() {
guard let layer = currentRadarLayer else { return }
self.nameLabel.font = layer.pinned ? AppFont.SFPro.bold(size: 14) : AppFont.SFPro.regular(size: 14)
self.pinButton.backgroundColor = !layer.pinned ? UIColor.black : UIColor(hex: 0x242B2E).withAlphaComponent(0.57)
self.pinButton.tintColor = !layer.pinned ? UIColor.white : UIColor(hex: 0xD9D9D9)
self.delegate?.cellPinButtonTouched(atLayer: layer)
} }
} }
...@@ -56,14 +79,14 @@ private extension RadarLayerCell { ...@@ -56,14 +79,14 @@ private extension RadarLayerCell {
} }
func prepareNameLabel() { func prepareNameLabel() {
nameLabel.lineBreakMode = .byTruncatingTail nameLabel.lineBreakMode = .byTruncatingMiddle
nameLabel.font = AppFont.SFPro.regular(size: 14) nameLabel.font = AppFont.SFPro.regular(size: 14)
contentView.addSubview(nameLabel) contentView.addSubview(nameLabel)
nameLabel.snp.makeConstraints { (make) in nameLabel.snp.makeConstraints { (make) in
make.left.equalToSuperview().inset(15) make.left.equalToSuperview().inset(15)
make.centerY.equalToSuperview() make.centerY.equalToSuperview()
make.right.equalTo(pinButton.snp.left).inset(8).priority(999) make.right.equalTo(pinButton.snp.left).offset(-8).priority(999)
} }
} }
......
...@@ -25,7 +25,7 @@ class RadarLayersCellFactory: CellFactoryProtocol { ...@@ -25,7 +25,7 @@ class RadarLayersCellFactory: CellFactoryProtocol {
init(radarViewModel:RadarViewModel) { init(radarViewModel:RadarViewModel) {
self.radarViewModel = radarViewModel self.radarViewModel = radarViewModel
sections = [LayerSection(type: .weather, rowsCount: radarViewModel.weatherLayers.count), sections = [LayerSection(type: .weather, rowsCount: radarViewModel.weatherLayers.count),
LayerSection(type: .severe, rowsCount: 0)] LayerSection(type: .severe, rowsCount: radarViewModel.severeLayers.count)]
} }
var numberOfSections: Int { var numberOfSections: Int {
...@@ -42,13 +42,32 @@ class RadarLayersCellFactory: CellFactoryProtocol { ...@@ -42,13 +42,32 @@ class RadarLayersCellFactory: CellFactoryProtocol {
func cellFromTableView(tableView: UITableView, indexPath: IndexPath) -> UITableViewCell { func cellFromTableView(tableView: UITableView, indexPath: IndexPath) -> UITableViewCell {
let cell = dequeueReusableCell(type: RadarLayerCell.self, tableView: tableView, indexPath: indexPath) let cell = dequeueReusableCell(type: RadarLayerCell.self, tableView: tableView, indexPath: indexPath)
cell.delegate = self
switch sections[indexPath.section].type { switch sections[indexPath.section].type {
case .weather: case .weather:
cell.configure(weatherLayer: radarViewModel.weatherLayers[indexPath.row]) cell.configure(radarLayer: radarViewModel.weatherLayers[indexPath.row])
cell.isSelected = radarViewModel.weatherLayers[indexPath.row].layer.id == radarViewModel.selectedLayer?.layer.id
case .severe: case .severe:
break cell.configure(radarLayer: radarViewModel.severeLayers[indexPath.row])
cell.isSelected = radarViewModel.severeLayers[indexPath.row].layer.id == radarViewModel.selectedLayer?.layer.id
} }
return cell return cell
} }
func didSelectRow(indexPath:IndexPath) {
switch sections[indexPath.section].type {
case .weather:
radarViewModel.select(layer: radarViewModel.weatherLayers[indexPath.row])
case .severe:
radarViewModel.select(layer: radarViewModel.severeLayers[indexPath.row])
}
}
}
//MARK:- RadarLayer cell delegate
extension RadarLayersCellFactory: RadarLayerCellDelegate {
func cellPinButtonTouched(atLayer: RadarLayer) {
radarViewModel.updatePinnedState(forLayer: atLayer)
}
} }
...@@ -48,12 +48,12 @@ class MapLegendView: UIView { ...@@ -48,12 +48,12 @@ class MapLegendView: UIView {
} }
//Public //Public
public func configure(weatherLayer:WeatherLayer) { public func configure(radarLayer:RadarLayer) {
legendGradient.set(colors: weatherLayer.legendColors) legendGradient.set(colors: radarLayer.layer.colors)
buttonGradient.colors = weatherLayer.legendColors buttonGradient.colors = radarLayer.layer.colors
legendLabelsStackView.removeAll() legendLabelsStackView.removeAll()
weatherLayer.values.enumerated().forEach { radarLayer.layer.values.enumerated().forEach {
let label = UILabel() let label = UILabel()
label.font = AppFont.SFPro.regular(size: 10) label.font = AppFont.SFPro.regular(size: 10)
label.text = $1 label.text = $1
......
...@@ -7,6 +7,10 @@ ...@@ -7,6 +7,10 @@
import UIKit import UIKit
protocol MapPinnedLayersViewDelegate:class {
func didSelectLayer(layerId:String)
}
class MapPinnedLayersView: UIView { class MapPinnedLayersView: UIView {
//Private //Private
private let pinContainer = UIView() private let pinContainer = UIView()
...@@ -14,6 +18,12 @@ class MapPinnedLayersView: UIView { ...@@ -14,6 +18,12 @@ class MapPinnedLayersView: UIView {
private let scrollView = UIScrollView() private let scrollView = UIScrollView()
private let stackView = UIStackView() private let stackView = UIStackView()
//Public
weak var delegate: MapPinnedLayersViewDelegate?
public var isEmpty:Bool {
return stackView.arrangedSubviews.count < 2
}
init() { init() {
super.init(frame: .zero) super.init(frame: .zero)
...@@ -21,16 +31,6 @@ class MapPinnedLayersView: UIView { ...@@ -21,16 +31,6 @@ class MapPinnedLayersView: UIView {
prepareScrollView() prepareScrollView()
prepareStackView() prepareStackView()
updateUI() updateUI()
for index in 0..<6 {
let button = PinnedlLayerButton(name: "Temperature")
button.isSelected = index == 0
if index == 5 {
button.configureForAdd()
}
stackView.addArrangedSubview(button)
}
stackView.layoutIfNeeded()
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
...@@ -43,27 +43,40 @@ class MapPinnedLayersView: UIView { ...@@ -43,27 +43,40 @@ class MapPinnedLayersView: UIView {
} }
//Public //Public
public func setPinnedLayers(layers:[WeatherLayer]) { public func setPinnedLayers(layers:[RadarLayer]) {
stackView.removeAll() stackView.removeAll()
layers.enumerated().forEach { //Add button
let button = PinnedlLayerButton(name: $1.name) let addButton = PinnedlLayerButton()
button.isSelected = $0 == 0 addButton.configureForAdd()
stackView.addArrangedSubview(button) addButton.addTarget(self, action: #selector(handleLayerButton(button:)), for: .touchUpInside)
stackView.addArrangedSubview(addButton)
if $0 == layers.count - 1 {
let addButton = PinnedlLayerButton(name: "") layers.forEach {
addButton.configureForAdd() let button = PinnedlLayerButton(radarLayer: $0)
stackView.addArrangedSubview(addButton) button.isSelected = false
} button.addTarget(self, action: #selector(handleLayerButton(button:)), for: .touchUpInside)
stackView.insertArrangedSubview(button, at: 0)
} }
stackView.layoutIfNeeded() stackView.layoutIfNeeded()
} }
public func selectLayer(radarLayer:RadarLayer) {
stackView.arrangedSubviews.forEach {
if let layerButton = $0 as? PinnedlLayerButton {
layerButton.isSelected = radarLayer.layer.id == layerButton.layerId
}
}
}
//Private //Private
private func updateUI() { private func updateUI() {
self.backgroundColor = ThemeManager.currentTheme.containerBackgroundColor self.backgroundColor = ThemeManager.currentTheme.containerBackgroundColor
} }
@objc private func handleLayerButton(button:PinnedlLayerButton) {
delegate?.didSelectLayer(layerId: button.layerId)
}
} }
//MARK:- Prepare Pinned Layers //MARK:- Prepare Pinned Layers
...@@ -123,13 +136,19 @@ private extension MapPinnedLayersView { ...@@ -123,13 +136,19 @@ private extension MapPinnedLayersView {
//MARK:- PinnedLayer Button //MARK:- PinnedLayer Button
private class PinnedlLayerButton: UIControl { private class PinnedlLayerButton: UIControl {
//Private
private let gradient = CAGradientLayer() private let gradient = CAGradientLayer()
private let nameLabel = UILabel() private let nameLabel = UILabel()
private var configuredForAdd = false private var configuredForAdd = false
init(name:String) { //Public
let layerId:String
init(radarLayer:RadarLayer? = nil) {
self.layerId = radarLayer?.layer.id ?? ""
super.init(frame: .zero) super.init(frame: .zero)
nameLabel.text = name
nameLabel.text = radarLayer?.layer.name
prepareView() prepareView()
prepareGradient() prepareGradient()
...@@ -183,6 +202,7 @@ private class PinnedlLayerButton: UIControl { ...@@ -183,6 +202,7 @@ private class PinnedlLayerButton: UIControl {
self.layer.borderWidth = 1 self.layer.borderWidth = 1
self.nameLabel.textColor = ThemeManager.currentTheme.graphTintColor self.nameLabel.textColor = ThemeManager.currentTheme.graphTintColor
self.nameLabel.text = "general.add".localized().capitalized + " +" self.nameLabel.text = "general.add".localized().capitalized + " +"
self.isSelected = false
self.configuredForAdd = true self.configuredForAdd = true
} }
......
...@@ -29,13 +29,13 @@ class RadarMapLayersController: UIViewController { ...@@ -29,13 +29,13 @@ class RadarMapLayersController: UIViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
view.backgroundColor = UIColor.black.withAlphaComponent(0.5) prepareController()
prepareTableView() prepareTableView()
} }
override func viewDidLayoutSubviews() { override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews() super.viewDidLayoutSubviews()
self.tableView.layer.shadowPath = CGPath(rect: self.view.bounds, transform: nil) self.view.layer.shadowPath = CGPath(rect: self.view.bounds, transform: nil)
} }
@objc private func handleCloseButton() { @objc private func handleCloseButton() {
...@@ -46,16 +46,17 @@ class RadarMapLayersController: UIViewController { ...@@ -46,16 +46,17 @@ class RadarMapLayersController: UIViewController {
//MARK:- Prepare //MARK:- Prepare
private extension RadarMapLayersController { private extension RadarMapLayersController {
func prepareController() { func prepareController() {
view.clipsToBounds = false
view.backgroundColor = .black
view.layer.shadowColor = UIColor.black.withAlphaComponent(0.12).cgColor
view.layer.shadowRadius = 8
view.layer.shadowOffset = .init(width: 0, height: 3)
view.layer.shadowOpacity = 1
} }
func prepareTableView() { func prepareTableView() {
cellFactory.registerCells(on: tableView) cellFactory.registerCells(on: tableView)
tableView.clipsToBounds = false tableView.clipsToBounds = false
tableView.layer.shadowColor = UIColor.black.withAlphaComponent(0.12).cgColor
tableView.layer.shadowRadius = 8
tableView.layer.shadowOffset = .init(width: 0, height: 3)
tableView.layer.shadowOpacity = 1
tableView.backgroundColor = ThemeManager.currentTheme.baseBackgroundColor tableView.backgroundColor = ThemeManager.currentTheme.baseBackgroundColor
tableView.tableHeaderView = UIView(frame: .init(origin: .zero, size: CGSize(width: 0, height: 0.01))) tableView.tableHeaderView = UIView(frame: .init(origin: .zero, size: CGSize(width: 0, height: 0.01)))
tableView.dataSource = self tableView.dataSource = self
...@@ -151,6 +152,11 @@ extension RadarMapLayersController: UITableViewDelegate { ...@@ -151,6 +152,11 @@ extension RadarMapLayersController: UITableViewDelegate {
return container return container
} }
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
cellFactory.didSelectRow(indexPath: indexPath)
tableView.reloadData()
}
} }
//MARK:- Transitioning Delegate //MARK:- Transitioning Delegate
......
...@@ -55,9 +55,7 @@ class RadarViewController: UIViewController { ...@@ -55,9 +55,7 @@ class RadarViewController: UIViewController {
prepareMapButtons() prepareMapButtons()
prepareMapTimeControl() prepareMapTimeControl()
updateUI() updateUI()
initialConfigure()
centerMap()
cityButton.configure(with: radarViewModel.location)
} }
//Private //Private
...@@ -75,6 +73,17 @@ class RadarViewController: UIViewController { ...@@ -75,6 +73,17 @@ class RadarViewController: UIViewController {
mapView.setRegion(region, animated: true) mapView.setRegion(region, animated: true)
} }
private func initialConfigure() {
self.centerMap()
cityButton.configure(with: radarViewModel.location)
pinnedLayersView.setPinnedLayers(layers: radarViewModel.pinnedLayers)
if let selectedLayer = radarViewModel.selectedLayer {
legendView.configure(radarLayer: selectedLayer)
pinnedLayersView.selectLayer(radarLayer: selectedLayer)
}
}
@objc private func handleCityButton() { @objc private func handleCityButton() {
} }
...@@ -161,7 +170,8 @@ private extension RadarViewController { ...@@ -161,7 +170,8 @@ private extension RadarViewController {
} }
func prepareMapPinnedLayers() { func prepareMapPinnedLayers() {
pinnedLayersView.setPinnedLayers(layers: radarViewModel.weatherLayers) pinnedLayersView.delegate = self
pinnedLayersView.setPinnedLayers(layers: radarViewModel.pinnedLayers)
view.addSubview(pinnedLayersView) view.addSubview(pinnedLayersView)
pinnedLayersView.snp.makeConstraints { (make) in pinnedLayersView.snp.makeConstraints { (make) in
...@@ -182,7 +192,6 @@ private extension RadarViewController { ...@@ -182,7 +192,6 @@ private extension RadarViewController {
} }
//Legend //Legend
legendView.configure(weatherLayer: radarViewModel.weatherLayers[6])
view.addSubview(legendView) view.addSubview(legendView)
legendView.snp.makeConstraints { (make) in legendView.snp.makeConstraints { (make) in
make.right.equalToSuperview().inset(8) make.right.equalToSuperview().inset(8)
...@@ -233,9 +242,28 @@ private extension RadarViewController { ...@@ -233,9 +242,28 @@ private extension RadarViewController {
} }
//MARK:- ViewModel Delegate //MARK:- ViewModel Delegate
extension RadarViewController: ViewModelDelegate { extension RadarViewController: RadarViewModelDelegate {
func viewModelDidChange<P>(model: P) where P : ViewModelProtocol { func viewModelDidChange<P>(model: P) where P : ViewModelProtocol {
self.centerMap() self.centerMap()
cityButton.configure(with: radarViewModel.location) cityButton.configure(with: radarViewModel.location)
} }
func viewModel(model: RadarViewModel, didSelectLayer layer: RadarLayer) {
pinnedLayersView.selectLayer(radarLayer: layer)
legendView.configure(radarLayer: layer)
}
func viewModelPinnedLayersDidChange(model: RadarViewModel) {
pinnedLayersView.setPinnedLayers(layers: radarViewModel.pinnedLayers)
if let selectedLayer = radarViewModel.selectedLayer {
pinnedLayersView.selectLayer(radarLayer: selectedLayer)
}
}
}
//MARK:- PinnedLayersView Delegate
extension RadarViewController: MapPinnedLayersViewDelegate {
func didSelectLayer(layerId: String) {
radarViewModel.select(layerId: layerId)
}
} }
...@@ -7,14 +7,31 @@ ...@@ -7,14 +7,31 @@
import UIKit import UIKit
protocol RadarViewModelDelegate: ViewModelDelegate {
func viewModel(model:RadarViewModel, didSelectLayer layer:RadarLayer)
func viewModelPinnedLayersDidChange(model:RadarViewModel)
}
class RadarViewModel: ViewModelProtocol { class RadarViewModel: ViewModelProtocol {
//Public //Public
public weak var delegate:ViewModelDelegate? public weak var delegate:RadarViewModelDelegate?
public var weatherLayers:[WeatherLayer] { public private(set) var weatherLayers:[RadarLayer]
return WeatherLayers.allLayers public private(set) var severeLayers:[RadarLayer]
public var pinnedLayers:[RadarLayer] {
return weatherLayers.filter{ $0.pinned } + severeLayers.filter{ $0.pinned }
} }
public var pinnedLayers:[WeatherLayer] { public var selectedLayer:RadarLayer? {
return WeatherLayers.allLayers.filter{ $0.pinned } let selectedLayerId = Settings.shared.selectedLayerId
if let weatherSelectedLayer = (weatherLayers.first{$0.layer.id == selectedLayerId}) {
return weatherSelectedLayer
}
if let severeSelectedLayer = (severeLayers.first{$0.layer.id == selectedLayerId}) {
return severeSelectedLayer
}
return nil
} }
//Private //Private
...@@ -24,8 +41,50 @@ class RadarViewModel: ViewModelProtocol { ...@@ -24,8 +41,50 @@ class RadarViewModel: ViewModelProtocol {
} }
init() { init() {
let pinnedLayerIds = Settings.shared.pinnedLayerIds
//Fill weather layers
weatherLayers = WeatherLayerType.allCases.map{ RadarLayer(pinned: pinnedLayerIds.contains($0.id), layer: $0) }
severeLayers = SevereLayerType.allCases.map{ RadarLayer(pinned: pinnedLayerIds.contains($0.id), layer: $0) }
locationManager.add(delegate: self) locationManager.add(delegate: self)
} }
public func updatePinnedState(forLayer layer:RadarLayer) {
//Weather
if let weatherIndex = (weatherLayers.firstIndex{$0.layer.id == layer.layer.id}) {
weatherLayers[weatherIndex].pinned = !weatherLayers[weatherIndex].pinned
}
//Severe
if let severeIndex = (severeLayers.firstIndex{$0.layer.id == layer.layer.id}) {
severeLayers[severeIndex].pinned = !severeLayers[severeIndex].pinned
}
//Save changes
Settings.shared.pinnedLayerIds = self.pinnedLayers.map{$0.layer.id}
delegate?.viewModelPinnedLayersDidChange(model: self)
}
public func select(layer:RadarLayer) {
Settings.shared.selectedLayerId = layer.layer.id
delegate?.viewModel(model: self, didSelectLayer: layer)
}
public func select(layerId:String) {
var layer:RadarLayer?
if let weatherLayer = (weatherLayers.firstIndex{ $0.layer.id == layerId }) {
layer = weatherLayers[weatherLayer]
}
if let severeLayer = (severeLayers.firstIndex{ $0.layer.id == layerId }) {
layer = severeLayers[severeLayer]
}
guard let selectedLayer = layer else { return }
Settings.shared.selectedLayerId = layerId
delegate?.viewModel(model: self, didSelectLayer: selectedLayer)
}
} }
//MARK:- LocationManager Delegate //MARK:- LocationManager Delegate
......
...@@ -14,14 +14,14 @@ ...@@ -14,14 +14,14 @@
<key>AlgoliaSearchClient.xcscheme_^#shared#^_</key> <key>AlgoliaSearchClient.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>20</integer> <integer>7</integer>
</dict> </dict>
<key>BezierKit.xcscheme</key> <key>BezierKit.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>1</integer> <integer>0</integer>
</dict> </dict>
<key>Cirque.xcscheme</key> <key>Cirque.xcscheme</key>
<dict> <dict>
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
<key>Cirque.xcscheme_^#shared#^_</key> <key>Cirque.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>18</integer> <integer>3</integer>
</dict> </dict>
<key>Firebase.xcscheme</key> <key>Firebase.xcscheme</key>
<dict> <dict>
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
<key>Firebase.xcscheme_^#shared#^_</key> <key>Firebase.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>16</integer> <integer>18</integer>
</dict> </dict>
<key>FirebaseABTesting.xcscheme</key> <key>FirebaseABTesting.xcscheme</key>
<dict> <dict>
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
<key>FirebaseABTesting.xcscheme_^#shared#^_</key> <key>FirebaseABTesting.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>4</integer> <integer>16</integer>
</dict> </dict>
<key>FirebaseAnalytics.xcscheme</key> <key>FirebaseAnalytics.xcscheme</key>
<dict> <dict>
...@@ -69,7 +69,7 @@ ...@@ -69,7 +69,7 @@
<key>FirebaseAnalytics.xcscheme_^#shared#^_</key> <key>FirebaseAnalytics.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>8</integer> <integer>12</integer>
</dict> </dict>
<key>FirebaseCore.xcscheme</key> <key>FirebaseCore.xcscheme</key>
<dict> <dict>
...@@ -81,7 +81,7 @@ ...@@ -81,7 +81,7 @@
<key>FirebaseCore.xcscheme_^#shared#^_</key> <key>FirebaseCore.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>15</integer> <integer>17</integer>
</dict> </dict>
<key>FirebaseCoreDiagnostics.xcscheme</key> <key>FirebaseCoreDiagnostics.xcscheme</key>
<dict> <dict>
...@@ -105,7 +105,7 @@ ...@@ -105,7 +105,7 @@
<key>FirebaseCrashlytics.xcscheme_^#shared#^_</key> <key>FirebaseCrashlytics.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>19</integer> <integer>20</integer>
</dict> </dict>
<key>FirebaseInstallations.xcscheme</key> <key>FirebaseInstallations.xcscheme</key>
<dict> <dict>
...@@ -129,7 +129,7 @@ ...@@ -129,7 +129,7 @@
<key>FirebaseRemoteConfig.xcscheme_^#shared#^_</key> <key>FirebaseRemoteConfig.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>23</integer> <integer>22</integer>
</dict> </dict>
<key>Flurry-iOS-SDK.xcscheme</key> <key>Flurry-iOS-SDK.xcscheme</key>
<dict> <dict>
...@@ -141,7 +141,7 @@ ...@@ -141,7 +141,7 @@
<key>Flurry-iOS-SDK.xcscheme_^#shared#^_</key> <key>Flurry-iOS-SDK.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>24</integer> <integer>4</integer>
</dict> </dict>
<key>GoogleAppMeasurement.xcscheme</key> <key>GoogleAppMeasurement.xcscheme</key>
<dict> <dict>
...@@ -153,7 +153,7 @@ ...@@ -153,7 +153,7 @@
<key>GoogleAppMeasurement.xcscheme_^#shared#^_</key> <key>GoogleAppMeasurement.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>10</integer> <integer>24</integer>
</dict> </dict>
<key>GoogleDataTransport.xcscheme</key> <key>GoogleDataTransport.xcscheme</key>
<dict> <dict>
...@@ -165,7 +165,7 @@ ...@@ -165,7 +165,7 @@
<key>GoogleDataTransport.xcscheme_^#shared#^_</key> <key>GoogleDataTransport.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>5</integer> <integer>21</integer>
</dict> </dict>
<key>GoogleUtilities.xcscheme</key> <key>GoogleUtilities.xcscheme</key>
<dict> <dict>
...@@ -177,7 +177,7 @@ ...@@ -177,7 +177,7 @@
<key>GoogleUtilities.xcscheme_^#shared#^_</key> <key>GoogleUtilities.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>3</integer> <integer>10</integer>
</dict> </dict>
<key>Localize-Swift.xcscheme</key> <key>Localize-Swift.xcscheme</key>
<dict> <dict>
...@@ -189,7 +189,7 @@ ...@@ -189,7 +189,7 @@
<key>Localize-Swift.xcscheme_^#shared#^_</key> <key>Localize-Swift.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>11</integer> <integer>5</integer>
</dict> </dict>
<key>Logging.xcscheme</key> <key>Logging.xcscheme</key>
<dict> <dict>
...@@ -201,7 +201,7 @@ ...@@ -201,7 +201,7 @@
<key>Logging.xcscheme_^#shared#^_</key> <key>Logging.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>17</integer> <integer>15</integer>
</dict> </dict>
<key>MORichNotification.xcscheme</key> <key>MORichNotification.xcscheme</key>
<dict> <dict>
...@@ -213,7 +213,7 @@ ...@@ -213,7 +213,7 @@
<key>MORichNotification.xcscheme_^#shared#^_</key> <key>MORichNotification.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>7</integer> <integer>19</integer>
</dict> </dict>
<key>MoEngage-iOS-SDK.xcscheme</key> <key>MoEngage-iOS-SDK.xcscheme</key>
<dict> <dict>
...@@ -225,14 +225,14 @@ ...@@ -225,14 +225,14 @@
<key>MoEngage-iOS-SDK.xcscheme_^#shared#^_</key> <key>MoEngage-iOS-SDK.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>13</integer> <integer>14</integer>
</dict> </dict>
<key>Pods-1Weather.xcscheme</key> <key>Pods-1Weather.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>2</integer> <integer>1</integer>
</dict> </dict>
<key>PromisesObjC.xcscheme</key> <key>PromisesObjC.xcscheme</key>
<dict> <dict>
...@@ -244,14 +244,14 @@ ...@@ -244,14 +244,14 @@
<key>PromisesObjC.xcscheme_^#shared#^_</key> <key>PromisesObjC.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>21</integer> <integer>23</integer>
</dict> </dict>
<key>SnapKit.xcscheme</key> <key>SnapKit.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>4</integer> <integer>2</integer>
</dict> </dict>
<key>XMLCoder.xcscheme</key> <key>XMLCoder.xcscheme</key>
<dict> <dict>
...@@ -263,7 +263,7 @@ ...@@ -263,7 +263,7 @@
<key>XMLCoder.xcscheme_^#shared#^_</key> <key>XMLCoder.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>14</integer> <integer>8</integer>
</dict> </dict>
<key>nanopb.xcscheme</key> <key>nanopb.xcscheme</key>
<dict> <dict>
...@@ -275,7 +275,7 @@ ...@@ -275,7 +275,7 @@
<key>nanopb.xcscheme_^#shared#^_</key> <key>nanopb.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>12</integer> <integer>13</integer>
</dict> </dict>
</dict> </dict>
<key>SuppressBuildableAutocreation</key> <key>SuppressBuildableAutocreation</key>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment