Commit 24b1d100 by Dmitry Stepanets

[iOS-154]: Finished precipitation minutely forecast

parent 68b65e12
...@@ -108,20 +108,23 @@ private extension MinutelyForecastDetailsView { ...@@ -108,20 +108,23 @@ private extension MinutelyForecastDetailsView {
separator.snp.makeConstraints { make in separator.snp.makeConstraints { make in
make.width.equalTo(1) make.width.equalTo(1)
make.height.equalToSuperview().multipliedBy(0.65) make.height.equalToSuperview().multipliedBy(0.65)
make.right.equalTo(tempLabel.snp.left).offset(-6) make.left.equalToSuperview().inset(70)
make.centerY.equalToSuperview()
}
tempLabel.snp.makeConstraints { make in
make.left.equalTo(separator.snp.right).offset(8)
make.centerY.equalToSuperview() make.centerY.equalToSuperview()
} }
forecastImage.snp.makeConstraints { make in forecastImage.snp.makeConstraints { make in
make.width.height.equalTo(28) make.width.height.equalTo(28)
make.centerY.equalToSuperview() make.centerY.equalToSuperview()
make.left.equalTo(tempLabel.snp.right).offset(4)
make.right.equalToSuperview().inset(8) make.right.equalToSuperview().inset(8)
} }
tempLabel.snp.makeConstraints { make in
make.right.equalTo(forecastImage.snp.left).offset(-2)
make.centerY.equalToSuperview()
}
} }
func prepareTriangle() { func prepareTriangle() {
......
...@@ -114,6 +114,7 @@ private class SwipeNudgeView: UIView { ...@@ -114,6 +114,7 @@ private class SwipeNudgeView: UIView {
class MinutelyForecastView: UIView { class MinutelyForecastView: UIView {
//Private //Private
private let kLevelWidth = 3 private let kLevelWidth = 3
private let kScrollViewRightInset: CGFloat = 20
private let detailsInfoView = MinutelyForecastDetailsView() private let detailsInfoView = MinutelyForecastDetailsView()
private let swipeNudgeView = SwipeNudgeView() private let swipeNudgeView = SwipeNudgeView()
private let levelsStackView = UIStackView() private let levelsStackView = UIStackView()
...@@ -159,7 +160,7 @@ class MinutelyForecastView: UIView { ...@@ -159,7 +160,7 @@ class MinutelyForecastView: UIView {
override func layoutSubviews() { override func layoutSubviews() {
super.layoutSubviews() super.layoutSubviews()
let leftInset = detailsInfoView.frame.origin.x - scrollView.frame.origin.x + detailsInfoView.frame.width / 2 let leftInset = (scrollView.bounds.width - kScrollViewRightInset) / 2
if scrollView.contentInset.left != leftInset { if scrollView.contentInset.left != leftInset {
scrollView.contentInset = .init(top: 0, left: leftInset, bottom: 0, right: leftInset + 20) scrollView.contentInset = .init(top: 0, left: leftInset, bottom: 0, right: leftInset + 20)
scrollView.setContentOffset(.init(x: -leftInset, y: 0), animated: false) scrollView.setContentOffset(.init(x: -leftInset, y: 0), animated: false)
...@@ -229,7 +230,7 @@ class MinutelyForecastView: UIView { ...@@ -229,7 +230,7 @@ class MinutelyForecastView: UIView {
timeZone: location?.timeZone ?? .current, timeZone: location?.timeZone ?? .current,
colors: kTemperatureColors) colors: kTemperatureColors)
case .precipitation: case .precipitation:
self.detailsInfoView.configure(valueStirng: "\(Int(minutelyItem.precipitation * 100))%", self.detailsInfoView.configure(valueStirng: minutelyItem.precipitation.settingsConverted.string,
date: minutelyItem.time, date: minutelyItem.time,
weatherImage: minutelyItem.weatherTypeImage, weatherImage: minutelyItem.weatherTypeImage,
timeZone: location?.timeZone ?? .current, timeZone: location?.timeZone ?? .current,
...@@ -361,14 +362,14 @@ class MinutelyForecastView: UIView { ...@@ -361,14 +362,14 @@ class MinutelyForecastView: UIView {
private func updatePrecipitationChart() { private func updatePrecipitationChart() {
guard guard
let maxPrecip = (minutelyForecast.compactMap{ $0.precipitation }.max{ $0 < $1 }), let maxPrecip = (minutelyForecast.compactMap{ $0.precipitation }.max{ $0.settingsConvertedValue < $1.settingsConvertedValue }),
let minPrecip = (minutelyForecast.compactMap{ $0.precipitation }.min{ $0 < $1 }) let minPrecip = (minutelyForecast.compactMap{ $0.precipitation }.min{ $0.settingsConvertedValue < $1.settingsConvertedValue })
else { else {
return return
} }
var uniqPrecips = minutelyForecast.compactMap{ $0.precipitation }.unique().sorted{$0 > $1} var uniqPrecips = minutelyForecast.compactMap{ $0.precipitation }.unique().sorted{$0.settingsConvertedValue > $1.settingsConvertedValue}
if uniqPrecips.count > 4 { if uniqPrecips.count > 4 {
let uniqMax = uniqPrecips.removeFirst() let uniqMax = uniqPrecips.removeFirst()
let uniqMin = uniqPrecips.removeLast() let uniqMin = uniqPrecips.removeLast()
...@@ -384,7 +385,7 @@ class MinutelyForecastView: UIView { ...@@ -384,7 +385,7 @@ class MinutelyForecastView: UIView {
for precipitation in uniqPrecips { for precipitation in uniqPrecips {
let label = UILabel() let label = UILabel()
label.text = "\(Int(precipitation * 100))%" label.text = precipitation.settingsConverted.shortString
label.font = AppFont.SFPro.regular(size: 10) label.font = AppFont.SFPro.regular(size: 10)
label.setContentHuggingPriority(.fittingSizeLevel, for: .vertical) label.setContentHuggingPriority(.fittingSizeLevel, for: .vertical)
label.sizeToFit() label.sizeToFit()
...@@ -394,8 +395,9 @@ class MinutelyForecastView: UIView { ...@@ -394,8 +395,9 @@ class MinutelyForecastView: UIView {
for index in 0..<minutelyForecast.count { for index in 0..<minutelyForecast.count {
let view = MinutelyLevelView(forecastType: .precipitation) let view = MinutelyLevelView(forecastType: .precipitation)
levelsStackView.addArrangedSubview(view) levelsStackView.addArrangedSubview(view)
let diff = maxPrecip - minPrecip == 0 ? 1 : maxPrecip - minPrecip let diff = maxPrecip.settingsConvertedValue - minPrecip.settingsConvertedValue == 0 ? 1
let level = (0.05 + 0.9 * ((minutelyForecast[index].precipitation - minPrecip) / diff)) : maxPrecip.settingsConvertedValue - minPrecip.settingsConvertedValue
let level = (0.05 + 0.9 * ((minutelyForecast[index].precipitation.settingsConvertedValue - minPrecip.settingsConvertedValue) / diff))
view.snp.makeConstraints { make in view.snp.makeConstraints { make in
make.width.equalTo(kLevelWidth) make.width.equalTo(kLevelWidth)
make.height.equalToSuperview().multipliedBy(level) make.height.equalToSuperview().multipliedBy(level)
...@@ -444,7 +446,6 @@ private extension MinutelyForecastView { ...@@ -444,7 +446,6 @@ private extension MinutelyForecastView {
//Constraints //Constraints
detailsInfoView.snp.makeConstraints { make in detailsInfoView.snp.makeConstraints { make in
make.width.equalTo(158)
make.height.equalTo(50) make.height.equalTo(50)
make.top.equalToSuperview() make.top.equalToSuperview()
make.centerX.equalToSuperview() make.centerX.equalToSuperview()
...@@ -483,7 +484,7 @@ private extension MinutelyForecastView { ...@@ -483,7 +484,7 @@ private extension MinutelyForecastView {
scrollView.snp.makeConstraints { make in scrollView.snp.makeConstraints { make in
make.left.equalToSuperview().inset(42) make.left.equalToSuperview().inset(42)
make.top.equalTo(detailsInfoView.snp.bottom).offset(8) make.top.equalTo(detailsInfoView.snp.bottom).offset(8)
make.right.equalToSuperview().inset(20) make.right.equalToSuperview().inset(kScrollViewRightInset)
make.bottom.equalToSuperview().inset(40) make.bottom.equalToSuperview().inset(40)
} }
} }
......
...@@ -72,6 +72,8 @@ class SettingsDetailsViewModel: ViewModelProtocol { ...@@ -72,6 +72,8 @@ class SettingsDetailsViewModel: ViewModelProtocol {
Settings.shared.pressureType = pressures[index] Settings.shared.pressureType = pressures[index]
case .distance: case .distance:
Settings.shared.distanceType = distances[index] Settings.shared.distanceType = distances[index]
case .rainfall:
Settings.shared.rainfallType = rainFalls[index]
default: default:
break break
} }
......
...@@ -21,6 +21,15 @@ public extension Measurement { ...@@ -21,6 +21,15 @@ public extension Measurement {
return fmt return fmt
} }
private static func fractionFormatter(style: Formatter.UnitStyle, unitOptions: MeasurementFormatter.UnitOptions = .providedUnit) -> MeasurementFormatter {
let fmt = MeasurementFormatter.oneWeatherSharedFormatter
fmt.locale = Settings.shared.locale
fmt.unitStyle = style
fmt.unitOptions = unitOptions
fmt.numberFormatter.maximumFractionDigits = 2
return fmt
}
var string:String { var string:String {
return Measurement.formatter(style: .medium).string(from: self) return Measurement.formatter(style: .medium).string(from: self)
} }
...@@ -78,3 +87,21 @@ public extension Pressure { ...@@ -78,3 +87,21 @@ public extension Pressure {
} }
} }
public extension Rainfall {
var settingsConvertedValue: Double {
return self.converted(to: Settings.shared.rainfallType).value
}
var settingsConverted: Measurement {
return self.converted(to: Settings.shared.rainfallType)
}
var string:String {
return Measurement.fractionFormatter(style: .medium).string(from: self)
}
var shortString: String {
return String(format: "%.2f", self.value)
}
}
...@@ -343,11 +343,14 @@ public enum MoonPhase: String, Codable { ...@@ -343,11 +343,14 @@ public enum MoonPhase: String, Codable {
} }
} }
public class UnitRainfall: Dimension { public final class UnitRainfall: Dimension {
public static let inchesPerHour = UnitRainfall(symbol: "in/h", converter: UnitConverterLinear(coefficient: 1.0)) public static let inchesPerHour = UnitRainfall(symbol: "in/h", converter: UnitConverterLinear(coefficient: 1.0))
public static let millimetersPerHour = UnitRainfall(symbol: "mm/h", converter: UnitConverterLinear(coefficient: 25.4)) public static let millimetersPerHour = UnitRainfall(symbol: "mm/h", converter: UnitConverterLinear(coefficient: 0.03937))
public static let baseUnit = UnitRainfall.inchesPerHour public override class func baseUnit() -> UnitRainfall {
return inchesPerHour
}
} }
public struct Time: CustomStringConvertible, Codable { public struct Time: CustomStringConvertible, Codable {
......
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