Commit 2764ea06 by Dmitriy Stepanets

Working on WeatherLayer

parent bd5171f7
No preview for this file type
......@@ -60,6 +60,7 @@
CD3F6E6925FA59D4002DB99B /* ForecastDetailPeriodButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD3F6E6825FA59D4002DB99B /* ForecastDetailPeriodButton.swift */; };
CD3F6E6C25FA5A90002DB99B /* PeriodButtonProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD3F6E6B25FA5A90002DB99B /* PeriodButtonProtocol.swift */; };
CD4742D0261200500061AC95 /* TodayAlertCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD4742CF261200500061AC95 /* TodayAlertCell.swift */; };
CD524E352629A120002881E2 /* WeatherLayers.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD524E342629A120002881E2 /* WeatherLayers.swift */; };
CD55E0BB2615EE2400CC4DC7 /* PollutantView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD55E0BA2615EE2400CC4DC7 /* PollutantView.swift */; };
CD593BC226088A5900C93428 /* TimePeriodOffsetHolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD593BC126088A5900C93428 /* TimePeriodOffsetHolder.swift */; };
CD593BC926089FC100C93428 /* UITableView+HeaderSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD593BC826089FC100C93428 /* UITableView+HeaderSize.swift */; };
......@@ -130,6 +131,7 @@
CDE18DD825D16CB200C80ED9 /* NavigationCityButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE18DD725D16CB200C80ED9 /* NavigationCityButton.swift */; };
CDE2BF222609D4250085C930 /* ForecastWindSpeedCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE2BF212609D4250085C930 /* ForecastWindSpeedCell.swift */; };
CDE2BF252609D9140085C930 /* ForecastWindButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE2BF242609D9140085C930 /* ForecastWindButton.swift */; };
CDECDB052629A6600087F9F2 /* WeatherLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDECDB042629A6600087F9F2 /* WeatherLayer.swift */; };
CDEE8AD725DA882200C289DE /* ForecastPeriodButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDEE8AD625DA882200C289DE /* ForecastPeriodButton.swift */; };
CDF4808F261727E00076E9F5 /* CLAuthorizationStatus+Localized.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDF4808E261727E00076E9F5 /* CLAuthorizationStatus+Localized.swift */; };
CDF48092261729680076E9F5 /* UIApplication+Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDF48091261729680076E9F5 /* UIApplication+Settings.swift */; };
......@@ -260,6 +262,7 @@
CD3F6E6825FA59D4002DB99B /* ForecastDetailPeriodButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastDetailPeriodButton.swift; sourceTree = "<group>"; };
CD3F6E6B25FA5A90002DB99B /* PeriodButtonProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeriodButtonProtocol.swift; sourceTree = "<group>"; };
CD4742CF261200500061AC95 /* TodayAlertCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayAlertCell.swift; sourceTree = "<group>"; };
CD524E342629A120002881E2 /* WeatherLayers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeatherLayers.swift; sourceTree = "<group>"; };
CD55E0BA2615EE2400CC4DC7 /* PollutantView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollutantView.swift; sourceTree = "<group>"; };
CD593BC126088A5900C93428 /* TimePeriodOffsetHolder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimePeriodOffsetHolder.swift; sourceTree = "<group>"; };
CD593BC826089FC100C93428 /* UITableView+HeaderSize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableView+HeaderSize.swift"; sourceTree = "<group>"; };
......@@ -330,6 +333,7 @@
CDE18DD725D16CB200C80ED9 /* NavigationCityButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationCityButton.swift; sourceTree = "<group>"; };
CDE2BF212609D4250085C930 /* ForecastWindSpeedCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastWindSpeedCell.swift; sourceTree = "<group>"; };
CDE2BF242609D9140085C930 /* ForecastWindButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastWindButton.swift; sourceTree = "<group>"; };
CDECDB042629A6600087F9F2 /* WeatherLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeatherLayer.swift; sourceTree = "<group>"; };
CDEE8AD625DA882200C289DE /* ForecastPeriodButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastPeriodButton.swift; sourceTree = "<group>"; };
CDF4808E261727E00076E9F5 /* CLAuthorizationStatus+Localized.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CLAuthorizationStatus+Localized.swift"; sourceTree = "<group>"; };
CDF48091261729680076E9F5 /* UIApplication+Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIApplication+Settings.swift"; sourceTree = "<group>"; };
......@@ -894,6 +898,15 @@
path = Forecast;
sourceTree = "<group>";
};
CDECDB022629A5F50087F9F2 /* WeatherLayers */ = {
isa = PBXGroup;
children = (
CD524E342629A120002881E2 /* WeatherLayers.swift */,
CDECDB042629A6600087F9F2 /* WeatherLayer.swift */,
);
path = WeatherLayers;
sourceTree = "<group>";
};
CE28474C261597EB006C8DC5 /* Health */ = {
isa = PBXGroup;
children = (
......@@ -1004,6 +1017,7 @@
CEAFF08125DFC66F00DF4EBF /* Model */ = {
isa = PBXGroup;
children = (
CDECDB022629A5F50087F9F2 /* WeatherLayers */,
CEAFF09125DFC71D00DF4EBF /* HelperTypes.swift */,
CEDE4F0925EFA376007457E9 /* Protocols */,
CEAFF0A025E0FEF100DF4EBF /* ModelObjects */,
......@@ -1352,6 +1366,7 @@
CDE18DD125D166F900C80ED9 /* ForecastViewController.swift in Sources */,
CE8962AC26175DF500CA274A /* CoreCurrentWeather.swift in Sources */,
CE9F01BB261B31A6009BA500 /* CoreDataError.swift in Sources */,
CD524E352629A120002881E2 /* WeatherLayers.swift in Sources */,
CD39F2F525DE9571009FE398 /* ArrowButton.swift in Sources */,
CE8962A526175DF500CA274A /* _CoreHourlyWeather.swift in Sources */,
CEDE4E8325EEFD56007457E9 /* WdtLocationResponse.swift in Sources */,
......@@ -1429,6 +1444,7 @@
CDF8F12D26208E7B00DB384A /* MapCurrentTimeView.swift in Sources */,
CEAFF08325DFC67F00DF4EBF /* Location.swift in Sources */,
87C171EC25FF79CC00DA3464 /* EnvironmentManager.swift in Sources */,
CDECDB052629A6600087F9F2 /* WeatherLayer.swift in Sources */,
CEFB857226174F7A00C5CDD2 /* Storage.swift in Sources */,
CD82300725D6A73F00A05501 /* TodayConditionButton.swift in Sources */,
CDC6126A25E90C8800188DA7 /* GraphLineSettings.swift in Sources */,
......
//
// WeatherLayer.swift
// 1Weather
//
// Created by Dmitry Stepanets on 16.04.2021.
//
import UIKit
struct WeatherLayer {
var pinned:Bool
var name:String
var legendColors:[CGColor]
var values:[String]
}
//
// WeatherLayers.swift
// 1Weather
//
// Created by Dmitry Stepanets on 16.04.2021.
//
import UIKit
private enum WeatherLayerType:CaseIterable {
case radar
case clouds
case surfaceTemp
case dewPoint
case relativeHumidity
case windSpeed
case uvIndex
var name:String {
switch self {
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] {
switch self {
case .radar:
return ["Rain" , "Mixed", "Snow"]
case .clouds:
return ["Intense", "Weak"]
case .surfaceTemp:
return ["-40F", "0", "32", "70", "120"]
case .dewPoint:
return ["10", "20", "30", "40", "50", "60", "70"]
case .relativeHumidity:
return ["0%", "20", "50", "70", "100"]
case .windSpeed:
return ["0mph", "10", "20", "30", "40", "50"]
case .uvIndex:
return ["0", "1", "2", "3", "4", "6", "8", "10", "12", "14"]
}
}
var colors:[CGColor] {
switch self {
case .radar:
return [UIColor.red, UIColor.black].map{$0.cgColor}
case .clouds:
return [UIColor(hex: 0xbf0a04),
UIColor(hex: 0xfce500),
UIColor(hex: 0x00b6fc),
UIColor(hex: 0xadadad),
UIColor(hex: 0x000000)].map{$0.cgColor}
case .surfaceTemp:
return [UIColor(hex: 0x6406f6),
UIColor(hex: 0xa9f2ff),
UIColor(hex: 0xffeb30),
UIColor(hex: 0xff3700),
UIColor(hex: 0xff99ca),
UIColor(hex: 0xeeeeee),
UIColor(hex: 0xFF1D0E)].map{$0.cgColor}
case .dewPoint:
return [UIColor(hex: 0x0f720f),
UIColor(hex: 0x28de28),
UIColor(hex: 0x90de92),
UIColor(hex: 0xf2ff7e),
UIColor(hex: 0xffd22f),
UIColor(hex: 0xeb9308),
UIColor(hex: 0x943000)].map{$0.cgColor}
case .relativeHumidity:
return [UIColor(hex: 0x0f720f),
UIColor(hex: 0x28de28),
UIColor(hex: 0x90de92),
UIColor(hex: 0xf2ff7e),
UIColor(hex: 0xffd22f),
UIColor(hex: 0xeb9308),
UIColor(hex: 0x943000)].map{$0.cgColor}
case .windSpeed:
return [UIColor(hex: 0xf705fa),
UIColor(hex: 0xfc0503),
UIColor(hex: 0xe18e00),
UIColor(hex: 0xecfa0d),
UIColor(hex: 0x00c896),
UIColor(hex: 0x1b3cec),
UIColor(hex: 0xFFFFFF)].map{$0.cgColor}
case .uvIndex:
return [UIColor(hex: 0x5a5a50),
UIColor(hex: 0x73736e),
UIColor(hex: 0x919191),
UIColor(hex: 0x916e6e),
UIColor(hex: 0xc8af5a),
UIColor(hex: 0xf0f03c),
UIColor(hex: 0xdc8c0a),
UIColor(hex: 0xdc4600),
UIColor(hex: 0xd2190a),
UIColor(hex: 0xdc378c)].map{$0.cgColor}
}
}
}
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 {
}
......@@ -95,7 +95,7 @@
"tabBar.radar" = "radar";
"tabBar.menu" = "menu";
// Search
//Search
"search.popularCities" = "Popular cities";
"search.title" = "Search location";
"search.savedCities" = "saved cities";
......@@ -105,7 +105,7 @@
"search.error.deleteError" = "Failed to delete location.";
"search.accessibility.tapToSelectLocation" = "Tap to select this location";
// Location
//Location
"location.servicesAreTurnedOff" = "System location services are turned off.";
"location.blockedByPermission" = "Location access is blocked by permission settings.";
"location.goToSettings.title" = "Location Services";
......@@ -121,6 +121,13 @@
//Radar
"radar.layers.base" = "Base layer";
"radar.layers.severe" = "Severe weather layer";
"radar.weatherLayer.radar" = "Radar";
"radar.weatherLayer.clouds" = "Clouds";
"radar.weatherLayer.surfaceTemp" = "Surface Temperature";
"radar.weatherLayer.dewPoint" = "Dew Point";
"radar.weatherLayer.relativeHumidity" = "Relative Humidity";
"radar.weatherLayer.windSpeed" = "Wind Speed";
"radar.weatherLayer.uvIndex" = "UV Index";
//Menu
"menu.goPremium" = "Go premium";
......
......@@ -25,8 +25,8 @@ class RadarLayerCell: UITableViewCell {
fatalError("init(coder:) has not been implemented")
}
public func configure(text:String) {
nameLabel.text = text
public func configure(weatherLayer:WeatherLayer) {
nameLabel.text = weatherLayer.name
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
......
......@@ -8,26 +8,32 @@
import UIKit
private enum Section {
case base
case weather
case severe
}
private struct LayerSection {
let type:Section
let rows:[String]
let rowsCount:Int
}
class RadarLayersCellFactory: CellFactoryProtocol {
//Private
private let sections = [LayerSection(type: .base, rows: ["Temperature", "Precipitation", "Humidity", "Clouds", "Radar"]),
LayerSection(type: .severe, rows: ["None", "Fire", "Floods"])]
private let radarViewModel:RadarViewModel
private let sections:[LayerSection]
init(radarViewModel:RadarViewModel) {
self.radarViewModel = radarViewModel
sections = [LayerSection(type: .weather, rowsCount: radarViewModel.weatherLayers.count),
LayerSection(type: .severe, rowsCount: 0)]
}
var numberOfSections: Int {
return sections.count
}
func numberOfRows(inSection section: Int) -> Int {
return sections[section].rows.count
return sections[section].rowsCount
}
func registerCells(on tableView: UITableView) {
......@@ -36,7 +42,13 @@ class RadarLayersCellFactory: CellFactoryProtocol {
func cellFromTableView(tableView: UITableView, indexPath: IndexPath) -> UITableViewCell {
let cell = dequeueReusableCell(type: RadarLayerCell.self, tableView: tableView, indexPath: indexPath)
cell.configure(text: sections[indexPath.section].rows[indexPath.row])
switch sections[indexPath.section].type {
case .weather:
cell.configure(weatherLayer: radarViewModel.weatherLayers[indexPath.row])
case .severe:
break
}
return cell
}
}
......@@ -8,10 +8,7 @@
import UIKit
class MapLegendGradientView: UIView {
private let colors:[UIColor]
init(colors:[UIColor]) {
self.colors = colors
init() {
super.init(frame: .zero)
prepare()
}
......@@ -23,6 +20,11 @@ class MapLegendGradientView: UIView {
override class var layerClass: AnyClass {
return CAGradientLayer.self
}
public func set(colors:[CGColor]) {
guard let gradientLayer = self.layer as? CAGradientLayer else { return }
gradientLayer.colors = colors
}
}
//MARK:- Prepare
......@@ -32,7 +34,6 @@ private extension MapLegendGradientView {
self.backgroundColor = .clear
guard let gradientLayer = self.layer as? CAGradientLayer else { return }
gradientLayer.colors = self.colors.map{$0.cgColor}
gradientLayer.startPoint = .init(x: 0, y: 0.5)
gradientLayer.endPoint = .init(x: 1, y: 0.5)
}
......
......@@ -12,13 +12,10 @@ class MapLegendView: UIView {
//Private
private let kOpenWidth:CGFloat = 180
private let kCloseWidth:CGFloat = 40
private static let kPrecipitationColors = [UIColor(hex: 0x9c57fa),
UIColor(hex: 0x5ef0e8).withAlphaComponent(0.8),
UIColor(hex: 0x4ebaf6)]
private let button = UIButton()
private let viewGradient = CAGradientLayer()
private let buttonGradient = CAGradientLayer()
private let legendGradient = MapLegendGradientView(colors: MapLegendView.kPrecipitationColors)
private let legendGradient = MapLegendGradientView()
private let legendLabelsStackView = UIStackView()
private var legendLabels = [UILabel]()
private var isOpened = false
......@@ -50,6 +47,23 @@ class MapLegendView: UIView {
updateUI()
}
//Public
public func configure(weatherLayer:WeatherLayer) {
legendGradient.set(colors: weatherLayer.legendColors)
buttonGradient.colors = weatherLayer.legendColors
legendLabelsStackView.removeAll()
weatherLayer.values.enumerated().forEach {
let label = UILabel()
label.font = AppFont.SFPro.regular(size: 10)
label.text = $1
self.legendLabels.append(label)
legendLabelsStackView.addArrangedSubview(label)
}
legendLabelsStackView.layoutIfNeeded()
}
//Private
private func updateUI() {
switch interfaceStyle {
case .light:
......@@ -110,7 +124,6 @@ private extension MapLegendView {
}
func prepareButton() {
buttonGradient.colors = MapLegendView.kPrecipitationColors.map{$0.cgColor}
buttonGradient.startPoint = .init(x: 0, y: 0.5)
buttonGradient.endPoint = .init(x: 1, y: 0.5)
......@@ -148,14 +161,5 @@ private extension MapLegendView {
make.left.right.equalTo(legendGradient)
make.top.equalTo(legendGradient.snp.bottom).offset(6)
}
let values = ["1%", "25%", "50%", "100%"]
values.enumerated().forEach {
let label = UILabel()
label.font = AppFont.SFPro.regular(size: 10)
label.text = $1
self.legendLabels.append(label)
legendLabelsStackView.addArrangedSubview(label)
}
}
}
......@@ -42,6 +42,25 @@ class MapPinnedLayersView: UIView {
updateUI()
}
//Public
public func setPinnedLayers(layers:[WeatherLayer]) {
stackView.removeAll()
layers.enumerated().forEach {
let button = PinnedlLayerButton(name: $1.name)
button.isSelected = $0 == 0
stackView.addArrangedSubview(button)
if $0 == layers.count - 1 {
let addButton = PinnedlLayerButton(name: "")
addButton.configureForAdd()
stackView.addArrangedSubview(addButton)
}
}
stackView.layoutIfNeeded()
}
//Private
private func updateUI() {
self.backgroundColor = ThemeManager.currentTheme.containerBackgroundColor
}
......@@ -84,7 +103,7 @@ private extension MapPinnedLayersView {
scrollView.snp.makeConstraints { (make) in
make.left.equalTo(pinContainer.snp.right).offset(6)
make.right.equalToSuperview()
make.right.equalToSuperview().priority(999)
make.top.equalToSuperview().inset(8)
}
}
......
......@@ -9,11 +9,15 @@ import UIKit
class RadarMapLayersController: UIViewController {
//Private
private let cellFactory = RadarLayersCellFactory()
private let radarViewModel:RadarViewModel
private let cellFactory:RadarLayersCellFactory
private let tableView = UITableView(frame: .zero, style: .grouped)
init() {
init(radarViewModel:RadarViewModel) {
self.radarViewModel = radarViewModel
self.cellFactory = RadarLayersCellFactory(radarViewModel: radarViewModel)
super.init(nibName: nil, bundle: nil)
modalPresentationStyle = .custom
transitioningDelegate = self
}
......
......@@ -111,7 +111,7 @@ class RadarViewController: UIViewController {
}
@objc private func handleLayersButton() {
let layersViewController = RadarMapLayersController()
let layersViewController = RadarMapLayersController(radarViewModel: self.radarViewModel)
self.present(layersViewController, animated: true)
}
......@@ -161,6 +161,7 @@ private extension RadarViewController {
}
func prepareMapPinnedLayers() {
pinnedLayersView.setPinnedLayers(layers: radarViewModel.weatherLayers)
view.addSubview(pinnedLayersView)
pinnedLayersView.snp.makeConstraints { (make) in
......@@ -181,6 +182,7 @@ private extension RadarViewController {
}
//Legend
legendView.configure(weatherLayer: radarViewModel.weatherLayers[6])
view.addSubview(legendView)
legendView.snp.makeConstraints { (make) in
make.right.equalToSuperview().inset(8)
......
......@@ -10,6 +10,12 @@ import UIKit
class RadarViewModel: ViewModelProtocol {
//Public
public weak var delegate:ViewModelDelegate?
public var weatherLayers:[WeatherLayer] {
return WeatherLayers.allLayers
}
public var pinnedLayers:[WeatherLayer] {
return WeatherLayers.allLayers.filter{ $0.pinned }
}
//Private
private let locationManager = LocationManager.shared
......
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