Commit 7f340d29 by Dmitry Stepanets

[IOS-172]: Working on minutely UI and iteractions

parent 9cdcebe9
......@@ -3,22 +3,4 @@
uuid = "55281C35-FE9F-4CED-865E-FBED0E7393F6"
type = "0"
version = "2.0">
<Breakpoints>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "75F9A873-CE27-44A5-80C1-ACB69F8CF7B8"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "1Weather/UI/SharedViews/MinutelyForecastView/MinutelyForecastView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "283"
endingLineNumber = "283"
landmarkName = "scrollViewDidScroll(_:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>
......@@ -49,9 +49,10 @@ class MinutelyForecastDetailsView: UIView {
triangle.path = path
}
func configure(valueStirng: String, date: Date?, colors: [UIColor]) {
func configure(valueStirng: String, date: Date?, weatherImage: UIImage?, timeZone: TimeZone, colors: [UIColor]) {
gradient.colors = colors.map{ $0.cgColor }
triangle.fillColor = colors.last?.cgColor
formatter.timeZone = timeZone
if let forecastDate = date {
timeLabel.text = formatter.string(from: forecastDate)
......@@ -61,7 +62,7 @@ class MinutelyForecastDetailsView: UIView {
}
tempLabel.text = valueStirng
forecastImage.image = nil
forecastImage.image = weatherImage
}
}
......@@ -108,16 +109,15 @@ private extension MinutelyForecastDetailsView {
make.centerY.equalToSuperview()
}
tempLabel.snp.makeConstraints { make in
make.left.equalTo(separator.snp.right).offset(8)
forecastImage.snp.makeConstraints { make in
make.width.height.equalTo(28)
make.centerY.equalToSuperview()
make.right.equalToSuperview().inset(8)
}
forecastImage.snp.makeConstraints { make in
make.width.height.equalTo(28)
tempLabel.snp.makeConstraints { make in
make.right.equalTo(forecastImage.snp.left).offset(-2)
make.centerY.equalToSuperview()
// make.left.equalTo(tempLabel.snp.right).offset(4)
make.right.equalToSuperview().inset(12)
}
}
......
......@@ -56,8 +56,11 @@ class MinutelyForecastView: UIView {
private let verticalStackView = UIStackView()
private let scrollView = UIScrollView()
private let centerDashline = CAShapeLayer()
private let feedbackGenerator = UISelectionFeedbackGenerator()
private var levelsPositionXCache = [Int : CGFloat]()
private var weatherTypeCache = [Int : WeatherType]()
private var weatherTypeCache = [Int : UIImage]()
private var lastSelectedLevelIndex = 0
private var minutelyForecast = [MinutelyItem]()
private lazy var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "h:mm a"
......@@ -94,42 +97,50 @@ class MinutelyForecastView: UIView {
func configure(with location: Location) {
self.location = location
self.dateFormatter.timeZone = location.timeZone
centerDashline.strokeColor = kTemperatureColors.last?.cgColor
if !location.hourly.isEmpty {
self.detailsInfoView.configure(valueStirng: location.hourly.first?.temp?.shortString ?? "--",
date: location.hourly.first?.date,
colors: kTemperatureColors)
}
updateWeatherTypeCahce()
prepareMinutelyItems()
if let firstMinutelyItem = minutelyForecast.first {
self.updateDetailsView(minutelyItem: firstMinutelyItem)
}
updateChart()
}
private func updateWeatherTypeCahce() {
weatherTypeCache.removeAll()
private func updateDetailsView(minutelyItem: MinutelyItem) {
self.detailsInfoView.configure(valueStirng: minutelyItem.temp.shortString,
date: minutelyItem.time,
weatherImage: minutelyItem.weatherTypeImage,
timeZone: location?.timeZone ?? .current,
colors: kTemperatureColors)
}
private func prepareMinutelyItems() {
minutelyForecast.removeAll()
guard
let currentLocation = self.location,
let minutelyForecast = currentLocation.minutely
let location = self.location,
let forecastItems = location.minutely?.forecast
else {
return
}
let allHours = minutelyForecast.forecast.compactMap{ $0.hourComponent }
let maxHour = allHours.max{ $0 > $1 } ?? 0
for hourlyWeather in currentLocation.hourly {
guard let hourComponent = Calendar.current.dateComponents([.hour], from: hourlyWeather.date).hour else {
for var minutelyForecastItem in forecastItems {
guard
let hourly = (location.hourly.first {
let thisHour = $0.date
let nextHour = thisHour.addingTimeInterval(3600)
return minutelyForecastItem.time >= thisHour && minutelyForecastItem.time < nextHour
})
else {
continue
}
if hourComponent > maxHour {
return
}
weatherTypeCache[hourComponent] = hourlyWeather.type
minutelyForecastItem.weatherTypeImage = hourly.type.image(isDay: hourly.isDay)
minutelyForecast.append(minutelyForecastItem)
}
}
private func updateChart() {
verticalStackView.removeAll()
levelsStackView.removeAll()
......@@ -141,15 +152,14 @@ class MinutelyForecastView: UIView {
}
guard
let forecast = location?.minutely?.forecast,
let maxTemp = (forecast.compactMap{$0.temp}.max{$0.value < $1.value}),
let minTemp = (forecast.compactMap{$0.temp}.min{$0.value < $1.value})
let maxTemp = (minutelyForecast.compactMap{$0.temp}.max{ $0.value < $1.value} ),
let minTemp = (minutelyForecast.compactMap{$0.temp}.min{ $0.value < $1.value} )
else {
return
}
var uniqTemps = forecast.compactMap{$0.temp}.unique().sorted{$0.value > $1.value}
var uniqTemps = minutelyForecast.compactMap{$0.temp}.unique().sorted{$0.value > $1.value}
if uniqTemps.count > 4 {
let uniqMax = uniqTemps.removeFirst()
let uniqMin = uniqTemps.removeLast()
......@@ -172,20 +182,20 @@ class MinutelyForecastView: UIView {
verticalStackView.addArrangedSubview(label)
}
for index in 0..<forecast.count {
for index in 0..<minutelyForecast.count {
let view = MinutelyLevelView(forecastType: .temperature)
levelsStackView.addArrangedSubview(view)
let level = (0.05 + 0.9 * ((forecast[index].temp.value - minTemp.value) / (maxTemp.value - minTemp.value)))
let level = (0.05 + 0.9 * ((minutelyForecast[index].temp.value - minTemp.value) / (maxTemp.value - minTemp.value)))
view.snp.makeConstraints { make in
make.width.equalTo(kLevelWidth)
make.height.equalToSuperview().multipliedBy(level)
}
let minutes = Calendar.current.component(.minute, from: forecast[index].time)
let minutes = Calendar.current.component(.minute, from: minutelyForecast[index].time)
if minutes % 20 == 0 {
let label = UILabel()
label.font = AppFont.SFPro.bold(size: 12)
label.text = dateFormatter.string(from: forecast[index].time)
label.text = dateFormatter.string(from: minutelyForecast[index].time)
scrollView.addSubview(label)
label.snp.makeConstraints { make in
......@@ -276,10 +286,12 @@ extension MinutelyForecastView: UIScrollViewDelegate {
return
}
let forecast = location?.minutely?.forecast[cachedValue.key]
detailsInfoView.configure(valueStirng: forecast?.temp.shortString ?? "--",
date: forecast?.time,
colors: kTemperatureColors)
print("[min] Target current index \(cachedValue.key)")
self.updateDetailsView(minutelyItem: minutelyForecast[cachedValue.key])
if lastSelectedLevelIndex != cachedValue.key {
lastSelectedLevelIndex = cachedValue.key
feedbackGenerator.prepare()
feedbackGenerator.selectionChanged()
}
}
}
......@@ -6,6 +6,7 @@
//
import Foundation
import UIKit
public struct MinutelyItem {
public let time: Date
......@@ -13,7 +14,7 @@ public struct MinutelyItem {
public let precipitation: Double
public let windSpeed: WindSpeed
public let pressure: Pressure
public let hourComponent: Int?
public var weatherTypeImage: UIImage?
public init(time: Date, temp: Temperature, precipitation: Double, windSpeed: WindSpeed, pressure: Pressure) {
self.time = time
......@@ -21,9 +22,5 @@ public struct MinutelyItem {
self.precipitation = precipitation
self.windSpeed = windSpeed
self.pressure = pressure
let calendar = Calendar.current
let components = calendar.dateComponents([.hour], from: time)
self.hourComponent = components.hour
}
}
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