Commit c73bf18b by Dmitry Stepanets

Working on levels

parent 67758c81
...@@ -30,17 +30,29 @@ private class MinutelyLevelView: UIView { ...@@ -30,17 +30,29 @@ private class MinutelyLevelView: UIView {
} }
} }
private extension Sequence where Iterator.Element: Hashable {
func unique() -> [Iterator.Element] {
var seen: Set<Iterator.Element> = []
return filter { seen.insert($0).inserted }
}
}
class MinutelyForecastView: UIView { class MinutelyForecastView: UIView {
//Private //Private
private let kTemperatureColors = [UIColor(hex: 0xff934f), UIColor(hex: 0xff414a)] private let kTemperatureColors = [UIColor(hex: 0xff934f), UIColor(hex: 0xff414a)]
private let kPrecipitationColors = [UIColor(hex: 0x2d99ff), UIColor(hex: 0x8fc6fb)] private let kPrecipitationColors = [UIColor(hex: 0x2d99ff), UIColor(hex: 0x8fc6fb)]
private let detailsInfoView = UIView() private let detailsInfoView = UIView()
private let levelsStackView = UIStackView()
private let verticalStackView = UIStackView() private let verticalStackView = UIStackView()
private let scrollView = UIScrollView() private let scrollView = UIScrollView()
private var location: Location? private var location: Location?
init() { init() {
super.init(frame: .zero) super.init(frame: .zero)
prepareDetailView()
prepareVerticalStackView()
prepareScrollView()
} }
override func layoutSubviews() { override func layoutSubviews() {
...@@ -52,10 +64,38 @@ class MinutelyForecastView: UIView { ...@@ -52,10 +64,38 @@ class MinutelyForecastView: UIView {
func configure(with location: Location) { func configure(with location: Location) {
self.location = location self.location = location
updateView()
}
private func updateView() {
verticalStackView.removeAll()
levelsStackView.removeAll()
prepareDetailView() guard
prepareVerticalStackView() let forecast = location?.minutely?.forecast,
prepareScrollView() let maxTemp = (forecast.compactMap{$0.temp}.max{$0.value < $1.value})
else {
return
}
let uniqTemps = forecast.compactMap{$0.temp}.unique().sorted{$0.value > $1.value}
for temp in uniqTemps {
let label = UILabel()
label.text = temp.settingsConverted.shortString
label.font = AppFont.SFPro.regular(size: 10)
verticalStackView.addArrangedSubview(label)
}
for index in 0..<forecast.count {
let view = MinutelyLevelView()
levelsStackView.addArrangedSubview(view)
let level = uniqTemps.firstIndex {$0.value == forecast[index].temp.value} ?? 0
view.snp.makeConstraints { make in
make.width.equalTo(3)
make.height.equalToSuperview().multipliedBy(1/Double(max(1,level)))
}
}
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
...@@ -77,21 +117,13 @@ private extension MinutelyForecastView { ...@@ -77,21 +117,13 @@ private extension MinutelyForecastView {
} }
func prepareVerticalStackView() { func prepareVerticalStackView() {
verticalStackView.removeAll()
verticalStackView.axis = .vertical verticalStackView.axis = .vertical
verticalStackView.distribution = .fillProportionally verticalStackView.distribution = .fillProportionally
verticalStackView.alignment = .fill verticalStackView.alignment = .fill
verticalStackView.isBaselineRelativeArrangement = false verticalStackView.isBaselineRelativeArrangement = false
verticalStackView.isLayoutMarginsRelativeArrangement = false verticalStackView.isLayoutMarginsRelativeArrangement = false
for index in 0..<4 {
let label = UILabel()
label.text = "\(29 - index)°"
label.font = AppFont.SFPro.regular(size: 10)
verticalStackView.addArrangedSubview(label)
}
addSubview(verticalStackView) addSubview(verticalStackView)
verticalStackView.snp.makeConstraints { make in verticalStackView.snp.makeConstraints { make in
make.left.equalToSuperview().inset(20) make.left.equalToSuperview().inset(20)
make.top.equalTo(detailsInfoView.snp.bottom).offset(8) make.top.equalTo(detailsInfoView.snp.bottom).offset(8)
...@@ -100,10 +132,9 @@ private extension MinutelyForecastView { ...@@ -100,10 +132,9 @@ private extension MinutelyForecastView {
} }
func prepareScrollView() { func prepareScrollView() {
scrollView.backgroundColor = .red scrollView.backgroundColor = .lightGray
addSubview(scrollView) addSubview(scrollView)
let levelsStackView = UIStackView()
levelsStackView.axis = .horizontal levelsStackView.axis = .horizontal
levelsStackView.spacing = 2 levelsStackView.spacing = 2
levelsStackView.distribution = .fill levelsStackView.distribution = .fill
...@@ -120,14 +151,5 @@ private extension MinutelyForecastView { ...@@ -120,14 +151,5 @@ private extension MinutelyForecastView {
make.right.equalToSuperview().inset(20) make.right.equalToSuperview().inset(20)
make.bottom.equalToSuperview().inset(40) make.bottom.equalToSuperview().inset(40)
} }
for _ in 0..<300 {
let view = MinutelyLevelView()
levelsStackView.addArrangedSubview(view)
view.snp.makeConstraints { make in
make.width.equalTo(3)
make.height.equalToSuperview().multipliedBy(Double.random(in: 0...0.9))
}
}
} }
} }
...@@ -28,7 +28,7 @@ public class BlendMinutelySource: MinutelyForecastSource { ...@@ -28,7 +28,7 @@ public class BlendMinutelySource: MinutelyForecastSource {
private let kTempUnit = "F" private let kTempUnit = "F"
private lazy var dateFormatter: DateFormatter = { private lazy var dateFormatter: DateFormatter = {
let fmt = DateFormatter() let fmt = DateFormatter()
fmt.dateFormat = "yyyy-MM-dd'T'hh:mm:ss.sss'Z'" fmt.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
return fmt return fmt
}() }()
/// This queue is needed to synchronize access to locationsBeingUpdated. Also, to make logging more clear. /// This queue is needed to synchronize access to locationsBeingUpdated. Also, to make logging more clear.
...@@ -124,7 +124,13 @@ public class BlendMinutelySource: MinutelyForecastSource { ...@@ -124,7 +124,13 @@ public class BlendMinutelySource: MinutelyForecastSource {
completion(.success(forecast)) completion(.success(forecast))
} }
catch { catch {
completion(.failure(BlendMinutelySourceError.dataEncodingError(error.localizedDescription))) guard let bodyData = data else {
completion(.failure(BlendMinutelySourceError.dataEncodingError(error.localizedDescription)))
return
}
let body = String(data: bodyData, encoding: .utf8) ?? "N/A"
completion(.failure(BlendMinutelySourceError.dataEncodingError(body)))
} }
} }
.resume() .resume()
......
...@@ -31,6 +31,8 @@ public class LocationManager { ...@@ -31,6 +31,8 @@ public class LocationManager {
private let legacyMigrator = LegacyMigrationManager() private let legacyMigrator = LegacyMigrationManager()
private var defaultLocation = Location(deviceLocation: false, private var defaultLocation = Location(deviceLocation: false,
coordinates: .init(latitude: 37.3230, longitude: -122.0322), // Cupertino coordinates: .init(latitude: 37.3230, longitude: -122.0322), // Cupertino
region: "US",
cityName: "Cupertino",
timeZone: TimeZone(abbreviation: "PST")!) { timeZone: TimeZone(abbreviation: "PST")!) {
didSet { didSet {
if locations.count == 0 { if locations.count == 0 {
......
...@@ -8,11 +8,11 @@ ...@@ -8,11 +8,11 @@
import Foundation import Foundation
public struct MinutelyItem { public struct MinutelyItem {
let time: Date public let time: Date
let temp: Temperature public let temp: Temperature
let precipitation: Double public let precipitation: Double
let windSpeed: WindSpeed public let windSpeed: WindSpeed
let pressure: Pressure public let pressure: Pressure
public init(time: Date, temp: Temperature, precipitation: Double, windSpeed: WindSpeed, pressure: Pressure) { public init(time: Date, temp: Temperature, precipitation: Double, windSpeed: WindSpeed, pressure: Pressure) {
self.time = time self.time = time
......
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