Commit 21eee6bc by Dmitriy Stepanets

Merge branch 'master' into controls-navigationBar

# Conflicts:
#	1Weather.xcworkspace/xcuserdata/dstepanets.xcuserdatad/UserInterfaceState.xcuserstate
parents 5f7e1893 da2e4af8
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
CD6B303E25726960004B34B3 /* ThemeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD6B303D25726960004B34B3 /* ThemeProtocol.swift */; }; CD6B303E25726960004B34B3 /* ThemeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD6B303D25726960004B34B3 /* ThemeProtocol.swift */; };
CD6B304325726AD1004B34B3 /* DefaultTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD6B304225726AD1004B34B3 /* DefaultTheme.swift */; }; CD6B304325726AD1004B34B3 /* DefaultTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD6B304225726AD1004B34B3 /* DefaultTheme.swift */; };
CD71709025FA317700A63C27 /* ForecastTimePeriodView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD71708F25FA317700A63C27 /* ForecastTimePeriodView.swift */; }; CD71709025FA317700A63C27 /* ForecastTimePeriodView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD71708F25FA317700A63C27 /* ForecastTimePeriodView.swift */; };
CD71709325FA31C200A63C27 /* ForecastTimePeriod.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD71709225FA31C200A63C27 /* ForecastTimePeriod.swift */; };
CD80917B2578E4A8003541A4 /* UIViewController+Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD80917A2578E4A8003541A4 /* UIViewController+Alert.swift */; }; CD80917B2578E4A8003541A4 /* UIViewController+Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD80917A2578E4A8003541A4 /* UIViewController+Alert.swift */; };
CD822FF525D6817000A05501 /* CityForecastCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD822FF425D6817000A05501 /* CityForecastCell.swift */; }; CD822FF525D6817000A05501 /* CityForecastCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD822FF425D6817000A05501 /* CityForecastCell.swift */; };
CD822FFA25D6890900A05501 /* OneWeatherColorsAsset.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CD822FF925D6890900A05501 /* OneWeatherColorsAsset.xcassets */; }; CD822FFA25D6890900A05501 /* OneWeatherColorsAsset.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CD822FF925D6890900A05501 /* OneWeatherColorsAsset.xcassets */; };
...@@ -53,7 +52,6 @@ ...@@ -53,7 +52,6 @@
CDA5542825EF734200A2E08C /* TodayCellFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDA5542725EF734200A2E08C /* TodayCellFactory.swift */; }; CDA5542825EF734200A2E08C /* TodayCellFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDA5542725EF734200A2E08C /* TodayCellFactory.swift */; };
CDA5542D25EF7C9700A2E08C /* ReusableCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDA5542C25EF7C9700A2E08C /* ReusableCellProtocol.swift */; }; CDA5542D25EF7C9700A2E08C /* ReusableCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDA5542C25EF7C9700A2E08C /* ReusableCellProtocol.swift */; };
CDA5543025EFA13F00A2E08C /* Measurement+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDA5542F25EFA13F00A2E08C /* Measurement+String.swift */; }; CDA5543025EFA13F00A2E08C /* Measurement+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDA5542F25EFA13F00A2E08C /* Measurement+String.swift */; };
CDB8AA2225FB76FF00BF4D22 /* PeriodButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDB8AA2125FB76FF00BF4D22 /* PeriodButton.swift */; };
CDC6124F25E7964700188DA7 /* CityDayTimesCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC6124E25E7964700188DA7 /* CityDayTimesCell.swift */; }; CDC6124F25E7964700188DA7 /* CityDayTimesCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC6124E25E7964700188DA7 /* CityDayTimesCell.swift */; };
CDC6125325E79C8F00188DA7 /* DayTimeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC6125225E79C8F00188DA7 /* DayTimeView.swift */; }; CDC6125325E79C8F00188DA7 /* DayTimeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC6125225E79C8F00188DA7 /* DayTimeView.swift */; };
CDC6125725E7AB1A00188DA7 /* CityAirQualityCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC6125625E7AB1A00188DA7 /* CityAirQualityCell.swift */; }; CDC6125725E7AB1A00188DA7 /* CityAirQualityCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC6125625E7AB1A00188DA7 /* CityAirQualityCell.swift */; };
...@@ -123,7 +121,6 @@ ...@@ -123,7 +121,6 @@
CD6B303D25726960004B34B3 /* ThemeProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeProtocol.swift; sourceTree = "<group>"; }; CD6B303D25726960004B34B3 /* ThemeProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeProtocol.swift; sourceTree = "<group>"; };
CD6B304225726AD1004B34B3 /* DefaultTheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultTheme.swift; sourceTree = "<group>"; }; CD6B304225726AD1004B34B3 /* DefaultTheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultTheme.swift; sourceTree = "<group>"; };
CD71708F25FA317700A63C27 /* ForecastTimePeriodView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastTimePeriodView.swift; sourceTree = "<group>"; }; CD71708F25FA317700A63C27 /* ForecastTimePeriodView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastTimePeriodView.swift; sourceTree = "<group>"; };
CD71709225FA31C200A63C27 /* ForecastTimePeriod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastTimePeriod.swift; sourceTree = "<group>"; };
CD80917A2578E4A8003541A4 /* UIViewController+Alert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Alert.swift"; sourceTree = "<group>"; }; CD80917A2578E4A8003541A4 /* UIViewController+Alert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Alert.swift"; sourceTree = "<group>"; };
CD822FF425D6817000A05501 /* CityForecastCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CityForecastCell.swift; sourceTree = "<group>"; }; CD822FF425D6817000A05501 /* CityForecastCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CityForecastCell.swift; sourceTree = "<group>"; };
CD822FF925D6890900A05501 /* OneWeatherColorsAsset.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = OneWeatherColorsAsset.xcassets; sourceTree = "<group>"; }; CD822FF925D6890900A05501 /* OneWeatherColorsAsset.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = OneWeatherColorsAsset.xcassets; sourceTree = "<group>"; };
...@@ -146,7 +143,6 @@ ...@@ -146,7 +143,6 @@
CDA5542725EF734200A2E08C /* TodayCellFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayCellFactory.swift; sourceTree = "<group>"; }; CDA5542725EF734200A2E08C /* TodayCellFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayCellFactory.swift; sourceTree = "<group>"; };
CDA5542C25EF7C9700A2E08C /* ReusableCellProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReusableCellProtocol.swift; sourceTree = "<group>"; }; CDA5542C25EF7C9700A2E08C /* ReusableCellProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReusableCellProtocol.swift; sourceTree = "<group>"; };
CDA5542F25EFA13F00A2E08C /* Measurement+String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Measurement+String.swift"; sourceTree = "<group>"; }; CDA5542F25EFA13F00A2E08C /* Measurement+String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Measurement+String.swift"; sourceTree = "<group>"; };
CDB8AA2125FB76FF00BF4D22 /* PeriodButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeriodButton.swift; sourceTree = "<group>"; };
CDC6124E25E7964700188DA7 /* CityDayTimesCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CityDayTimesCell.swift; sourceTree = "<group>"; }; CDC6124E25E7964700188DA7 /* CityDayTimesCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CityDayTimesCell.swift; sourceTree = "<group>"; };
CDC6125225E79C8F00188DA7 /* DayTimeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DayTimeView.swift; sourceTree = "<group>"; }; CDC6125225E79C8F00188DA7 /* DayTimeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DayTimeView.swift; sourceTree = "<group>"; };
CDC6125625E7AB1A00188DA7 /* CityAirQualityCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CityAirQualityCell.swift; sourceTree = "<group>"; }; CDC6125625E7AB1A00188DA7 /* CityAirQualityCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CityAirQualityCell.swift; sourceTree = "<group>"; };
...@@ -220,7 +216,6 @@ ...@@ -220,7 +216,6 @@
CDEE8AD625DA882200C289DE /* ForecastPeriodButton.swift */, CDEE8AD625DA882200C289DE /* ForecastPeriodButton.swift */,
CD3F6E6825FA59D4002DB99B /* ForecastDetailPeriodButton.swift */, CD3F6E6825FA59D4002DB99B /* ForecastDetailPeriodButton.swift */,
CD3F6E6B25FA5A90002DB99B /* PeriodButtonProtocol.swift */, CD3F6E6B25FA5A90002DB99B /* PeriodButtonProtocol.swift */,
CDB8AA2125FB76FF00BF4D22 /* PeriodButton.swift */,
); );
path = ForecastTimePeriod; path = ForecastTimePeriod;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -528,7 +523,6 @@ ...@@ -528,7 +523,6 @@
CEAFF08B25DFC6BC00DF4EBF /* DailyWeather.swift */, CEAFF08B25DFC6BC00DF4EBF /* DailyWeather.swift */,
CEAFF08E25DFC6ED00DF4EBF /* HourlyWeather.swift */, CEAFF08E25DFC6ED00DF4EBF /* HourlyWeather.swift */,
CE578FD225F7E89400E8B85D /* DayTimeWeather.swift */, CE578FD225F7E89400E8B85D /* DayTimeWeather.swift */,
CD71709225FA31C200A63C27 /* ForecastTimePeriod.swift */,
); );
path = ModelObjects; path = ModelObjects;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -678,7 +672,6 @@ ...@@ -678,7 +672,6 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
CD82300325D69DE400A05501 /* CityConditionsCell.swift in Sources */, CD82300325D69DE400A05501 /* CityConditionsCell.swift in Sources */,
CDB8AA2225FB76FF00BF4D22 /* PeriodButton.swift in Sources */,
CEC526FD25E795F700DA58A5 /* WdtWeatherSource.swift in Sources */, CEC526FD25E795F700DA58A5 /* WdtWeatherSource.swift in Sources */,
CEAFF09225DFC71D00DF4EBF /* HelperTypes.swift in Sources */, CEAFF09225DFC71D00DF4EBF /* HelperTypes.swift in Sources */,
CDA5543025EFA13F00A2E08C /* Measurement+String.swift in Sources */, CDA5543025EFA13F00A2E08C /* Measurement+String.swift in Sources */,
...@@ -716,7 +709,6 @@ ...@@ -716,7 +709,6 @@
CDEE8AD725DA882200C289DE /* ForecastPeriodButton.swift in Sources */, CDEE8AD725DA882200C289DE /* ForecastPeriodButton.swift in Sources */,
CDE18DD125D166F900C80ED9 /* ForecastViewController.swift in Sources */, CDE18DD125D166F900C80ED9 /* ForecastViewController.swift in Sources */,
CD39F2F525DE9571009FE398 /* ArrowButton.swift in Sources */, CD39F2F525DE9571009FE398 /* ArrowButton.swift in Sources */,
CD71709325FA31C200A63C27 /* ForecastTimePeriod.swift in Sources */,
CEDE4E8325EEFD56007457E9 /* WdtLocationResponse.swift in Sources */, CEDE4E8325EEFD56007457E9 /* WdtLocationResponse.swift in Sources */,
CD8E041625F8F91B001785B6 /* ForecastCellFactory.swift in Sources */, CD8E041625F8F91B001785B6 /* ForecastCellFactory.swift in Sources */,
CDC6125325E79C8F00188DA7 /* DayTimeView.swift in Sources */, CDC6125325E79C8F00188DA7 /* DayTimeView.swift in Sources */,
......
...@@ -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>6</integer> <integer>3</integer>
</dict> </dict>
<key>PG (Playground) 1.xcscheme</key> <key>PG (Playground) 1.xcscheme</key>
<dict> <dict>
......
//
// ForecastTimePeriod.swift
// 1Weather
//
// Created by Dmitry Stepanets on 11.03.2021.
//
import UIKit
struct ForecastTimePeriod {
let daily:[DailyWeather]
let hourly:[HourlyWeather]
}
...@@ -14,7 +14,7 @@ struct WdtDailySummariesArray: Codable { ...@@ -14,7 +14,7 @@ struct WdtDailySummariesArray: Codable {
private static let dateFormatter:DateFormatter = { private static let dateFormatter:DateFormatter = {
let fmt = DateFormatter() let fmt = DateFormatter()
fmt.timeZone = TimeZone(abbreviation: "PST") fmt.timeZone = TimeZone(abbreviation: "PST")
fmt.dateFormat = "MM/dd/YYYY" fmt.dateFormat = "MM/dd/yyyy"
return fmt return fmt
}() }()
......
...@@ -13,7 +13,7 @@ struct WdtHourlySummariesArray: Codable { ...@@ -13,7 +13,7 @@ struct WdtHourlySummariesArray: Codable {
private static let dateFormatter:DateFormatter = { private static let dateFormatter:DateFormatter = {
let fmt = DateFormatter() let fmt = DateFormatter()
fmt.timeZone = TimeZone(abbreviation: "PST") fmt.timeZone = TimeZone(abbreviation: "PST")
fmt.dateFormat = "YYYY-MM-dd HH:mm:ss" fmt.dateFormat = "yyyy-MM-dd HH:mm:ss"
return fmt return fmt
}() }()
......
...@@ -46,7 +46,7 @@ struct WdtDailySummary: Codable { ...@@ -46,7 +46,7 @@ struct WdtDailySummary: Codable {
public func toAppModel(timeZone: TimeZone, updatedAt: Date) -> DailyWeather? { public func toAppModel(timeZone: TimeZone, updatedAt: Date) -> DailyWeather? {
let log = WdtDailySummary.log let log = WdtDailySummary.log
let dateFormatter = DateFormatter() let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/YYYY" dateFormatter.dateFormat = "MM/dd/yyyy"
dateFormatter.timeZone = timeZone dateFormatter.timeZone = timeZone
guard let date = dateFormatter.date(from: dateLocal) else { guard let date = dateFormatter.date(from: dateLocal) else {
log.error("Failed to parse date from: \(dateLocal)") log.error("Failed to parse date from: \(dateLocal)")
...@@ -80,7 +80,7 @@ struct WdtDailySummary: Codable { ...@@ -80,7 +80,7 @@ struct WdtDailySummary: Codable {
let sunMoonDateFormatter = DateFormatter() let sunMoonDateFormatter = DateFormatter()
sunMoonDateFormatter.timeZone = TimeZone(identifier: "UTC") sunMoonDateFormatter.timeZone = TimeZone(identifier: "UTC")
sunMoonDateFormatter.dateFormat = "YYYY-MM-dd HH:mm:ss" sunMoonDateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
if let sunriseUtc = sunriseUtc { if let sunriseUtc = sunriseUtc {
result.sunrise = sunMoonDateFormatter.date(from: sunriseUtc) result.sunrise = sunMoonDateFormatter.date(from: sunriseUtc)
} }
......
...@@ -39,7 +39,7 @@ struct WdtHourlySummary: Codable { ...@@ -39,7 +39,7 @@ struct WdtHourlySummary: Codable {
public func toAppModel(timeZone: TimeZone, updatedAt: Date) -> HourlyWeather? { public func toAppModel(timeZone: TimeZone, updatedAt: Date) -> HourlyWeather? {
let log = WdtHourlySummary.log let log = WdtHourlySummary.log
let dateFormatter = DateFormatter() let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "YYYY-MM-dd HH:mm:ss" dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.timeZone = timeZone dateFormatter.timeZone = timeZone
guard let date = dateFormatter.date(from: dateTimeLocal) else { guard let date = dateFormatter.date(from: dateTimeLocal) else {
......
...@@ -45,7 +45,7 @@ struct WdtSurfaceObservation: Codable { ...@@ -45,7 +45,7 @@ struct WdtSurfaceObservation: Codable {
public func toAppModel(timeZone: TimeZone, updatedAt: Date) -> CurrentWeather? { public func toAppModel(timeZone: TimeZone, updatedAt: Date) -> CurrentWeather? {
let log = WdtSurfaceObservation.log let log = WdtSurfaceObservation.log
let dateFormatter = DateFormatter() let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "YYYY-MM-dd HH:mm:ss" dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.timeZone = timeZone dateFormatter.timeZone = timeZone
guard let date = dateFormatter.date(from: self.dateTimeLocal) else { guard let date = dateFormatter.date(from: self.dateTimeLocal) else {
...@@ -88,7 +88,7 @@ struct WdtSurfaceObservation: Codable { ...@@ -88,7 +88,7 @@ struct WdtSurfaceObservation: Codable {
let sunDateFormatter = DateFormatter() let sunDateFormatter = DateFormatter()
sunDateFormatter.timeZone = timeZone sunDateFormatter.timeZone = timeZone
sunDateFormatter.dateFormat = "YYYY-MM-dd hh:mm a" sunDateFormatter.dateFormat = "yyyy-MM-dd hh:mm a"
result.sunrise = sunDateFormatter.date(from: sunriseLocalDateTime) result.sunrise = sunDateFormatter.date(from: sunriseLocalDateTime)
result.sunset = sunDateFormatter.date(from: sunsetLocalDateTime) result.sunset = sunDateFormatter.date(from: sunsetLocalDateTime)
} }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
"version" : 1 "version" : 1
}, },
"properties" : { "properties" : {
"preserves-vector-representation" : true "preserves-vector-representation" : true,
"template-rendering-intent" : "original"
} }
} }
...@@ -7,11 +7,11 @@ ...@@ -7,11 +7,11 @@
//Forecast //Forecast
"forecast.sunny" = "Sunny"; "forecast.sunny" = "Sunny";
"forecast.clear" = "Clear";
"forecast.cloudy" = "Cloudy"; "forecast.cloudy" = "Cloudy";
"forecast.partlyCloudyDay" = "Partly Cloudy"; "forecast.partlyCloudyDay" = "Partly Cloudy";
"forecast.snowyDay" = "Snowy Day"; "forecast.snowyDay" = "Snowy Day";
"forecast.snowyNight" = "Snowy Night"; "forecast.snowyNight" = "Snowy Night";
"forecast.clearDay" = "Clear Day";
"forecast.clearNight" = "Clear Night"; "forecast.clearNight" = "Clear Night";
"forecast.partlyCloudyNight" = "Partly Cloudy Night"; "forecast.partlyCloudyNight" = "Partly Cloudy Night";
"forecast.thunderstorm" = "Thunderstorm"; "forecast.thunderstorm" = "Thunderstorm";
......
...@@ -6,21 +6,206 @@ ...@@ -6,21 +6,206 @@
// //
import UIKit import UIKit
import SnapKit
class ForecastDetailPeriodButton: PeriodButton { class ForecastDetailPeriodButton: UIControl, PeriodButtonProtocol {
private let kGraphInset:CGFloat = 10
private let kPrecipImageWidth:CGFloat = 20
private let dateLabel = UILabel()
private let weatherImageView = UIImageView()
private let weatherTypeLabel = UILabel()
private let maxTempLabel = UILabel()
private let minTempLabel = UILabel()
private let precipLabel = UILabel()
private let precipImageView = UIImageView()
private var precipImageWidth:Constraint?
private static var formatter: DateFormatter = {
let fmt = DateFormatter()
fmt.dateFormat = "d, E"
return fmt
}()
//Public
public var tinted: Bool {
return false
}
public var index = -1
var graphRect:CGRect {
let topInset = self.maxTempLabel.frame.origin.y + self.maxTempLabel.frame.size.height + kGraphInset
return .init(x: 0,
y: topInset,
width: self.bounds.width,
height: self.minTempLabel.frame.origin.y - topInset - kGraphInset)
}
required init() { required init() {
super.init() super.init(frame: .zero)
prepareButton()
prepareDateLabel()
prepareWeatherInfo()
preparePreicpitaitonView()
prepareTempLabels()
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
override func configure(dailyWeather: DailyWeather) { override var isSelected: Bool {
// didSet {
if isSelected {
self.backgroundColor = UIColor(hex: 0x1f67f3)
self.dateLabel.font = AppFont.SFPro.bold(size: 16)
self.dateLabel.textColor = .white
self.weatherTypeLabel.textColor = .white
self.maxTempLabel.font = AppFont.SFPro.bold(size: 16)
self.maxTempLabel.textColor = .white
self.minTempLabel.textColor = .white
self.precipLabel.textColor = .white
self.precipImageView.tintColor = .white
}
else {
self.backgroundColor = UIColor(hex: 0xeceef6)
self.dateLabel.font = AppFont.SFPro.regular(size: 16)
self.dateLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
self.weatherTypeLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
self.maxTempLabel.font = AppFont.SFPro.regular(size: 16)
self.maxTempLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
self.minTempLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
self.precipLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
self.precipImageView.tintColor = UIColor(hex: 0x1f67f3)
}
}
}
func configure(dailyWeather: DailyWeather) {
if Calendar.current.isDateInToday(dailyWeather.date) {
dateLabel.text = "day.today".localized()
}
else {
dateLabel.text = ForecastDetailPeriodButton.formatter.string(from: dailyWeather.date)
}
weatherImageView.image = dailyWeather.type.image(isDay: true)
weatherTypeLabel.text = dailyWeather.type.localized(isDay: true)
maxTempLabel.text = dailyWeather.maxTemp?.shortString
minTempLabel.text = dailyWeather.minTemp?.shortString
let percent = dailyWeather.precipitationProbability ?? 0
precipLabel.text = "\(percent)%"
precipImageView.isHidden = percent == 0
precipImageWidth?.layoutConstraints.first?.constant = percent == 0 ? 0 : kPrecipImageWidth
}
func configure(hourlyWeather: HourlyWeather) {
assertionFailure("Not implemented for this weather type")
}
}
private extension ForecastDetailPeriodButton {
func prepareButton() {
clipsToBounds = false
backgroundColor = UIColor.white
layer.cornerRadius = 12
layer.borderColor = UIColor(hex: 0xeceef6).cgColor
layer.borderWidth = 1 / UIScreen.main.scale
}
func prepareDateLabel() {
dateLabel.isUserInteractionEnabled = false
dateLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
dateLabel.font = AppFont.SFPro.regular(size: 14)
addSubview(dateLabel)
dateLabel.snp.makeConstraints { (make) in
make.top.equalToSuperview().inset(16)
make.centerX.equalToSuperview()
}
}
func prepareWeatherInfo() {
weatherImageView.isUserInteractionEnabled = false
weatherImageView.contentMode = .scaleAspectFit
addSubview(weatherImageView)
weatherImageView.snp.makeConstraints { (make) in
make.width.height.equalTo(28)
make.top.equalTo(dateLabel.snp.bottom).offset(8)
make.centerX.equalToSuperview()
make.left.right.equalToSuperview().inset(20)
}
weatherTypeLabel.isUserInteractionEnabled = false
weatherTypeLabel.textAlignment = .center
weatherTypeLabel.numberOfLines = 2
weatherTypeLabel.lineBreakMode = .byWordWrapping
weatherTypeLabel.font = AppFont.SFPro.regular(size: 12)
weatherTypeLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
addSubview(weatherTypeLabel)
weatherTypeLabel.snp.makeConstraints { (make) in
make.top.equalTo(weatherImageView.snp.bottom).offset(2)
make.centerX.equalToSuperview()
make.left.right.equalToSuperview().inset(4)
}
}
func prepareTempLabels() {
maxTempLabel.isUserInteractionEnabled = false
maxTempLabel.font = AppFont.SFPro.regular(size: 16)
maxTempLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
addSubview(maxTempLabel)
maxTempLabel.snp.makeConstraints { (make) in
make.top.equalTo(weatherImageView.snp.bottom).offset(34)
make.centerX.equalToSuperview()
}
minTempLabel.isUserInteractionEnabled = false
minTempLabel.font = AppFont.SFPro.regular(size: 12)
minTempLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
addSubview(minTempLabel)
minTempLabel.snp.makeConstraints { (make) in
make.bottom.equalTo(precipImageView.snp.top).offset(-28)
make.centerX.equalToSuperview()
}
} }
override func configure(hourlyWeather: HourlyWeather) { func preparePreicpitaitonView() {
// let container = UIView()
precipImageView.isUserInteractionEnabled = false
precipImageView.image = UIImage(named: "humidity")?.withRenderingMode(.alwaysTemplate)
precipImageView.tintColor = UIColor(hex: 0x1f67f3)
precipImageView.contentMode = .scaleAspectFit
container.addSubview(precipImageView)
precipImageView.snp.makeConstraints { (make) in
self.precipImageWidth = make.width.equalTo(kPrecipImageWidth).constraint
make.height.equalTo(12)
make.top.left.bottom.equalToSuperview()
}
precipLabel.isUserInteractionEnabled = false
precipLabel.textAlignment = .left
precipLabel.font = AppFont.SFPro.regular(size: 12)
precipLabel.textColor = ThemeManager.currentTheme.secondaryTextColor
container.addSubview(precipLabel)
precipLabel.snp.makeConstraints { (make) in
make.left.equalTo(precipImageView.snp.right).inset(2)
make.right.equalToSuperview()
}
addSubview(container)
container.snp.makeConstraints { (make) in
make.centerX.equalToSuperview()
make.bottom.equalToSuperview().inset(20)
}
} }
} }
...@@ -7,14 +7,14 @@ ...@@ -7,14 +7,14 @@
import UIKit import UIKit
class ForecastPeriodButton: PeriodButton { class ForecastPeriodButton: UIControl, PeriodButtonProtocol {
//Private //Private
private let hourlyFormatter: DateFormatter = { private static var hourlyFormatter: DateFormatter = {
let fmt = DateFormatter() let fmt = DateFormatter()
fmt.dateFormat = "h a" fmt.dateFormat = "h a"
return fmt return fmt
}() }()
private let dailyFormatter: DateFormatter = { private static var dailyFormatter: DateFormatter = {
let fmt = DateFormatter() let fmt = DateFormatter()
fmt.dateFormat = "d, E" fmt.dateFormat = "d, E"
return fmt return fmt
...@@ -25,19 +25,24 @@ class ForecastPeriodButton: PeriodButton { ...@@ -25,19 +25,24 @@ class ForecastPeriodButton: PeriodButton {
private let indicatorImageView = UIImageView() private let indicatorImageView = UIImageView()
private let minTempLabel = UILabel() private let minTempLabel = UILabel()
private let timeLabel = UILabel() private let timeLabel = UILabel()
//Public //Public
public var tinted: Bool {
return true
}
public var index = -1
var graphRect:CGRect { var graphRect:CGRect {
let topInset = self.tempLabel.frame.origin.y + self.tempLabel.frame.size.height + kGraphInset let topInset = self.tempLabel.frame.origin.y + self.tempLabel.frame.size.height + kGraphInset
return .init(x: 0, return .init(x: 0,
y: topInset, y: topInset,
width: self.bounds.width, width: self.bounds.width,
height: self.minTempLabel.frame.origin.y - self.tempLabel.frame.origin.y - tempLabel.frame.height) height: self.minTempLabel.frame.origin.y - topInset - kGraphInset)
} }
required init() { required init() {
super.init() super.init(frame: .zero)
prepareButton() prepareButton()
prepareForecastImage() prepareForecastImage()
...@@ -79,7 +84,7 @@ class ForecastPeriodButton: PeriodButton { ...@@ -79,7 +84,7 @@ class ForecastPeriodButton: PeriodButton {
} }
//Public //Public
override func configure(dailyWeather: DailyWeather) { func configure(dailyWeather: DailyWeather) {
self.tempLabel.text = dailyWeather.maxTemp?.shortString self.tempLabel.text = dailyWeather.maxTemp?.shortString
self.minTempLabel.text = dailyWeather.minTemp?.shortString self.minTempLabel.text = dailyWeather.minTemp?.shortString
self.indicatorImageView.image = nil self.indicatorImageView.image = nil
...@@ -88,15 +93,17 @@ class ForecastPeriodButton: PeriodButton { ...@@ -88,15 +93,17 @@ class ForecastPeriodButton: PeriodButton {
self.timeLabel.text = "day.today".localized() self.timeLabel.text = "day.today".localized()
} }
else { else {
self.timeLabel.text = dailyFormatter.string(from: dailyWeather.date) ForecastPeriodButton.dailyFormatter.timeZone = dailyWeather.timeZone
self.timeLabel.text = ForecastPeriodButton.dailyFormatter.string(from: dailyWeather.date)
} }
} }
override func configure(hourlyWeather: HourlyWeather) { func configure(hourlyWeather: HourlyWeather) {
self.tempLabel.text = hourlyWeather.temp?.shortString self.tempLabel.text = hourlyWeather.temp?.shortString
self.minTempLabel.text = nil self.minTempLabel.text = nil
self.indicatorImageView.image = nil self.indicatorImageView.image = nil
self.timeLabel.text = hourlyFormatter.string(from: hourlyWeather.date) ForecastPeriodButton.hourlyFormatter.timeZone = hourlyWeather.timeZone
self.timeLabel.text = ForecastPeriodButton.hourlyFormatter.string(from: hourlyWeather.date)
} }
} }
......
...@@ -20,22 +20,16 @@ class ForecastTimePeriodView: UIView { ...@@ -20,22 +20,16 @@ class ForecastTimePeriodView: UIView {
//Private //Private
private let scrollView = UIScrollView() private let scrollView = UIScrollView()
private let stackView = UIStackView() private let stackView = UIStackView()
private let buttonType:PeriodButton.Type
private var buttonProtocol:PeriodButtonProtocol.Type!
private let graphView = GraphView() private let graphView = GraphView()
private var graphRect:CGRect = .zero private var graphRect:CGRect = .zero
private var currentTimePeriod = TimePeriod.daily private var currentTimePeriod = TimePeriod.daily
private var dailyGraphPoints = DailyGraphPoints(maxTempPoints: [CGPoint](), minTempPoints: [CGPoint]()) private var dailyGraphPoints = DailyGraphPoints(maxTempPoints: [CGPoint](), minTempPoints: [CGPoint]())
private var hourlyGraphPoints = HourlyGraphPoints(points: [CGPoint]()) private var hourlyGraphPoints = HourlyGraphPoints(points: [CGPoint]())
private var forecastTimePeriod:ForecastTimePeriod = ForecastTimePeriod(daily: [DailyWeather](), hourly: [HourlyWeather]()) { private var daily = [DailyWeather]()
didSet { private var hourly = [HourlyWeather]()
rebuildButtons()
}
}
//MARK:- View life cycle //MARK:- View life cycle
init<T: PeriodButton>(buttonType: T.Type) { init() {
self.buttonType = buttonType
super.init(frame: .zero) super.init(frame: .zero)
preapreView() preapreView()
...@@ -43,77 +37,62 @@ class ForecastTimePeriodView: UIView { ...@@ -43,77 +37,62 @@ class ForecastTimePeriodView: UIView {
prepareStackView() prepareStackView()
prepareGraphView() prepareGraphView()
} }
convenience init<T: PeriodButtonProtocol>(buttonProtocol: T) {
self.init(buttonType: PeriodButton.self)
self.buttonProtocol = T.self
}
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
//Public //Public
public func set(forecastTimePeriod: ForecastTimePeriod) { public func set(location: Location) {
self.forecastTimePeriod = forecastTimePeriod self.daily = location.daily
self.hourly = location.hourly
} }
public func set(timePeriod:TimePeriod) { public func set(timePeriod:TimePeriod, buttonType: PeriodButtonProtocol.Type) {
self.currentTimePeriod = timePeriod self.currentTimePeriod = timePeriod
rebuildButtons() rebuildButtons(buttonType: buttonType)
} }
//Private //Private
private func createButton<T: PeriodButton>(typeThing:T.Type) -> T { private func rebuildButtons(buttonType: PeriodButtonProtocol.Type) {
return typeThing.init()
}
private func createFromProtocol<T: PeriodButtonProtocol>(typeThing: T.Type) -> T {
return typeThing.init()
}
private func rebuildButtons() {
stackView.arrangedSubviews.forEach { stackView.arrangedSubviews.forEach {
stackView.removeArrangedSubview($0) stackView.removeArrangedSubview($0)
$0.removeFromSuperview() $0.removeFromSuperview()
} }
let numberOfButtons:Int
switch currentTimePeriod { switch currentTimePeriod {
case .daily: case .daily:
for index in 0..<forecastTimePeriod.daily.count { numberOfButtons = daily.count
let forecastButton = self.createButton(typeThing: buttonType)
forecastButton.configure(dailyWeather: forecastTimePeriod.daily[index])
forecastButton.index = index
forecastButton.addTarget(self, action: #selector(handleForecastButton(button:)), for: .touchUpInside)
forecastButton.isSelected = index == 1
stackView.addArrangedSubview(forecastButton)
forecastButton.snp.makeConstraints { (make) in
make.height.equalToSuperview()
}
}
case .hourly: case .hourly:
for index in 0..<forecastTimePeriod.hourly.count { numberOfButtons = hourly.count
let forecastButton = self.createButton(typeThing: buttonType) }
forecastButton.configure(hourlyWeather: forecastTimePeriod.hourly[index])
forecastButton.index = index for index in 0..<numberOfButtons {
forecastButton.addTarget(self, action: #selector(handleForecastButton(button:)), for: .touchUpInside) let forecastButton = buttonType.init()
forecastButton.isSelected = index == 1 switch currentTimePeriod {
stackView.addArrangedSubview(forecastButton) case .daily:
forecastButton.configure(dailyWeather: daily[index])
forecastButton.snp.makeConstraints { (make) in case .hourly:
make.height.equalToSuperview() forecastButton.configure(hourlyWeather: hourly[index])
} }
forecastButton.index = index
forecastButton.addTarget(self, action: #selector(handleForecastButton(button:)), for: .touchUpInside)
forecastButton.isSelected = index == 1
stackView.addArrangedSubview(forecastButton)
forecastButton.snp.makeConstraints { (make) in
make.height.equalToSuperview()
} }
} }
stackView.layoutIfNeeded() stackView.layoutIfNeeded()
updateGraphLayout() updateGraphLayout()
} }
private func updateGraphLayout() { private func updateGraphLayout() {
print("[ForecastTimePeriod] Update graph layout") print("[ForecastTimePeriod] Update graph layout")
graphRect = (stackView.arrangedSubviews.first as? ForecastPeriodButton)?.graphRect ?? .zero graphRect = (stackView.arrangedSubviews.first as? PeriodButtonProtocol)?.graphRect ?? .zero
graphView.frame = .init(x: 0, graphView.frame = .init(x: 0,
y: graphRect.origin.y, y: graphRect.origin.y,
width: stackView.frame.width, width: stackView.frame.width,
...@@ -133,16 +112,16 @@ class ForecastTimePeriodView: UIView { ...@@ -133,16 +112,16 @@ class ForecastTimePeriodView: UIView {
} }
private func updateDailyGraphPoints() { private func updateDailyGraphPoints() {
let daysCount = forecastTimePeriod.daily.count let daysCount = daily.count
let maxTemps = (forecastTimePeriod.daily.map{ CGFloat($0.maxTemp?.localeValue ?? 0) }) let maxTemps = (daily.map{ CGFloat($0.maxTemp?.localeValue ?? 0) })
let topMaxTemp = maxTemps.max() ?? 0 let topMaxTemp = maxTemps.max() ?? 0
let minTemps = (forecastTimePeriod.daily.map{ CGFloat($0.minTemp?.localeValue ?? 0) }) let minTemps = (daily.map{ CGFloat($0.minTemp?.localeValue ?? 0) })
let topMinTemp = minTemps.max() ?? 0 let topMinTemp = minTemps.max() ?? 0
var maxPoints = [CGPoint]() var maxPoints = [CGPoint]()
var minPoints = [CGPoint]() var minPoints = [CGPoint]()
for index in 0..<daysCount { for index in 0..<daysCount {
guard let stackButton = stackView.arrangedSubviews[index] as? ForecastPeriodButton else { continue } guard let stackButton = stackView.arrangedSubviews[index] as? PeriodButtonProtocol else { continue }
let buttonRightSide = stackButton.frame.origin.x + stackButton.bounds.width let buttonRightSide = stackButton.frame.origin.x + stackButton.bounds.width
let buttonCenterX = (buttonRightSide + stackButton.frame.origin.x) / 2 let buttonCenterX = (buttonRightSide + stackButton.frame.origin.x) / 2
...@@ -157,11 +136,11 @@ class ForecastTimePeriodView: UIView { ...@@ -157,11 +136,11 @@ class ForecastTimePeriodView: UIView {
//Max //Max
var maxPointLevel = maxTempFrame.origin.y + ((topMaxTemp - maxTemps[index]) * levelHeight) + levelHeight var maxPointLevel = maxTempFrame.origin.y + ((topMaxTemp - maxTemps[index]) * levelHeight) + levelHeight
maxPointLevel = min(maxPointLevel, maxTempFrame.height + 5) maxPointLevel = min(maxPointLevel, maxTempFrame.height)
//Min //Min
var minPointLevel = minTempFrame.origin.y + ((topMinTemp - minTemps[index]) * levelHeight) + levelHeight var minPointLevel = minTempFrame.origin.y + ((topMinTemp - minTemps[index]) * levelHeight) + levelHeight
minPointLevel = min(minPointLevel, minTempFrame.height + minTempFrame.origin.y - 5) minPointLevel = min(minPointLevel, minTempFrame.height + minTempFrame.origin.y)
maxPoints.append(.init(x: buttonCenterX, y: maxPointLevel)) maxPoints.append(.init(x: buttonCenterX, y: maxPointLevel))
minPoints.append(.init(x: buttonCenterX, y: minPointLevel)) minPoints.append(.init(x: buttonCenterX, y: minPointLevel))
...@@ -171,14 +150,14 @@ class ForecastTimePeriodView: UIView { ...@@ -171,14 +150,14 @@ class ForecastTimePeriodView: UIView {
} }
private func updateHourlyGraphPoints() { private func updateHourlyGraphPoints() {
let hoursCount = forecastTimePeriod.hourly.count let hoursCount = hourly.count
let temps = (forecastTimePeriod.hourly.map{ CGFloat($0.temp?.localeValue ?? 0) }) let temps = (hourly.map{ CGFloat($0.temp?.localeValue ?? 0) })
let maxTemp = temps.max() ?? 0 let maxTemp = temps.max() ?? 0
var points = [CGPoint]() var points = [CGPoint]()
for index in 0..<hoursCount { for index in 0..<hoursCount {
guard let stackButton = stackView.arrangedSubviews[index] as? ForecastPeriodButton else { continue } guard let stackButton = stackView.arrangedSubviews[index] as? PeriodButtonProtocol else { continue }
let buttonRightSide = stackButton.frame.origin.x + stackButton.bounds.width let buttonRightSide = stackButton.frame.origin.x + stackButton.bounds.width
let buttonCenterX = (buttonRightSide + stackButton.frame.origin.x) / 2 let buttonCenterX = (buttonRightSide + stackButton.frame.origin.x) / 2
...@@ -188,8 +167,8 @@ class ForecastTimePeriodView: UIView { ...@@ -188,8 +167,8 @@ class ForecastTimePeriodView: UIView {
let tempFrame = CGRect(x: 0, y: 0, width: graphView.frame.width, height: graphView.frame.height) let tempFrame = CGRect(x: 0, y: 0, width: graphView.frame.width, height: graphView.frame.height)
var pointLevel = tempFrame.origin.y + ((maxTemp - temps[index]) * levelHeight) var pointLevel = tempFrame.origin.y + ((maxTemp - temps[index]) * levelHeight)
pointLevel = max(pointLevel, tempFrame.origin.y + 10) pointLevel = max(pointLevel, tempFrame.origin.y)
pointLevel = min(tempFrame.height - 10, pointLevel) pointLevel = min(tempFrame.height, pointLevel)
points.append(.init(x: buttonCenterX, y: pointLevel)) points.append(.init(x: buttonCenterX, y: pointLevel))
} }
...@@ -199,7 +178,7 @@ class ForecastTimePeriodView: UIView { ...@@ -199,7 +178,7 @@ class ForecastTimePeriodView: UIView {
private func drawGraph() { private func drawGraph() {
guard guard
let periodButtons = stackView.arrangedSubviews as? [ForecastPeriodButton], let periodButtons = stackView.arrangedSubviews as? [PeriodButtonProtocol],
let selectedButton = (periodButtons.first{ $0.isSelected }) let selectedButton = (periodButtons.first{ $0.isSelected })
else { else {
return return
...@@ -219,7 +198,9 @@ class ForecastTimePeriodView: UIView { ...@@ -219,7 +198,9 @@ class ForecastTimePeriodView: UIView {
print("[ForecastTimePeriod] Draw graph") print("[ForecastTimePeriod] Draw graph")
} }
private func tintGraphAt(button:ForecastPeriodButton) { private func tintGraphAt(button:PeriodButtonProtocol) {
guard button.tinted else { return }
switch currentTimePeriod { switch currentTimePeriod {
case .daily: case .daily:
self.graphView.tintGraphFrom(startPointX: button.frame.origin.x, self.graphView.tintGraphFrom(startPointX: button.frame.origin.x,
...@@ -233,9 +214,9 @@ class ForecastTimePeriodView: UIView { ...@@ -233,9 +214,9 @@ class ForecastTimePeriodView: UIView {
} }
} }
@objc private func handleForecastButton(button:ForecastPeriodButton) { @objc private func handleForecastButton(button:UIControl) {
stackView.arrangedSubviews.forEach { stackView.arrangedSubviews.forEach {
if let periodButton = $0 as? ForecastPeriodButton { if let periodButton = $0 as? PeriodButtonProtocol {
periodButton.isSelected = periodButton === button periodButton.isSelected = periodButton === button
if periodButton.isSelected { if periodButton.isSelected {
......
//
// PeriodButton.swift
// 1Weather
//
// Created by Dmitry Stepanets on 12.03.2021.
//
import UIKit
class PeriodButton: UIControl {
//Public
public var index:Int = -1
required init() {
super.init(frame: .zero)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func configure(dailyWeather: DailyWeather) {
}
public func configure(hourlyWeather: HourlyWeather) {
}
}
...@@ -7,13 +7,11 @@ ...@@ -7,13 +7,11 @@
import UIKit import UIKit
public protocol PeriodButtonProtocol { public protocol PeriodButtonProtocol: UIControl {
init() init()
func configure(dailyWeather: DailyWeather) func configure(dailyWeather: DailyWeather)
func configure(hourlyWeather: HourlyWeather) func configure(hourlyWeather: HourlyWeather)
} var index: Int { get set }
var graphRect:CGRect { get }
struct PeriodButtonType: PeriodButtonProtocol { var tinted:Bool { get }
func configure(dailyWeather: DailyWeather) {}
func configure(hourlyWeather: HourlyWeather) {}
} }
...@@ -12,10 +12,11 @@ class ForecastTimePeriodCell: UITableViewCell { ...@@ -12,10 +12,11 @@ class ForecastTimePeriodCell: UITableViewCell {
private let periodSegmentedControl = ForecastTimePeriodControl(items: ["forecast.timePeriod.daily".localized(), private let periodSegmentedControl = ForecastTimePeriodControl(items: ["forecast.timePeriod.daily".localized(),
"forecast.timePeriod.hourly".localized()]) "forecast.timePeriod.hourly".localized()])
private let forecastTimePeriodView = ForecastTimePeriodView(buttonType: ForecastDetailPeriodButton.self) private let forecastTimePeriodView = ForecastTimePeriodView()
private let gradientView = GradientView(startColor: UIColor(hex: 0xffffff).withAlphaComponent(0), private let gradientView = GradientView(startColor: UIColor(hex: 0xffffff).withAlphaComponent(0),
endColor: UIColor(hex: 0xdaddec), endColor: UIColor(hex: 0xdaddec),
opacity: 0.5) opacity: 0.5)
private var graphIsDrawn = false
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)
...@@ -32,12 +33,25 @@ class ForecastTimePeriodCell: UITableViewCell { ...@@ -32,12 +33,25 @@ class ForecastTimePeriodCell: UITableViewCell {
//Public //Public
public func configure(with location:Location) { public func configure(with location:Location) {
let forecastTimePeriod = ForecastTimePeriod(daily: location.daily, hourly: location.hourly) self.forecastTimePeriodView.set(location: location)
self.forecastTimePeriodView.set(forecastTimePeriod: forecastTimePeriod)
if graphIsDrawn == false {
self.handleSegmentDidChange()
self.graphIsDrawn = true
}
} }
@objc private func handleSegmentDidChange() { @objc private func handleSegmentDidChange() {
guard let timePeriod = TimePeriod(rawValue: self.periodSegmentedControl.selectedSegmentIndex) else {
return
}
switch timePeriod {
case .daily:
self.forecastTimePeriodView.set(timePeriod: timePeriod, buttonType: ForecastDetailPeriodButton.self)
case .hourly:
self.forecastTimePeriodView.set(timePeriod: timePeriod, buttonType: ForecastPeriodButton.self)
}
} }
} }
......
...@@ -11,10 +11,11 @@ class CityForecastTimePeriodCell: UITableViewCell { ...@@ -11,10 +11,11 @@ class CityForecastTimePeriodCell: UITableViewCell {
//Private //Private
private let periodSegmentedControl = ForecastTimePeriodControl(items: ["forecast.timePeriod.daily".localized(), private let periodSegmentedControl = ForecastTimePeriodControl(items: ["forecast.timePeriod.daily".localized(),
"forecast.timePeriod.hourly".localized()]) "forecast.timePeriod.hourly".localized()])
private let forecastTimePeriodView = ForecastTimePeriodView(buttonType: ForecastPeriodButton.self) private let forecastTimePeriodView = ForecastTimePeriodView()
private let summaryView = UIView() private let summaryView = UIView()
private let summaryImageView = UIImageView() private let summaryImageView = UIImageView()
private let summaryLabel = UILabel() private let summaryLabel = UILabel()
private var graphIsDrawn = false
//MARK:- Cell life cycle //MARK:- Cell life cycle
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
...@@ -32,8 +33,12 @@ class CityForecastTimePeriodCell: UITableViewCell { ...@@ -32,8 +33,12 @@ class CityForecastTimePeriodCell: UITableViewCell {
//Public //Public
public func configure(with location:Location) { public func configure(with location:Location) {
let forecastTimePeriod = ForecastTimePeriod(daily: location.daily, hourly: location.hourly) self.forecastTimePeriodView.set(location: location)
self.forecastTimePeriodView.set(forecastTimePeriod: forecastTimePeriod)
if graphIsDrawn == false {
self.handleSegmentDidChange()
self.graphIsDrawn = true
}
} }
@objc private func handleSegmentDidChange() { @objc private func handleSegmentDidChange() {
...@@ -41,7 +46,7 @@ class CityForecastTimePeriodCell: UITableViewCell { ...@@ -41,7 +46,7 @@ class CityForecastTimePeriodCell: UITableViewCell {
return return
} }
self.forecastTimePeriodView.set(timePeriod: timePeriod) self.forecastTimePeriodView.set(timePeriod: timePeriod, buttonType: ForecastPeriodButton.self)
} }
} }
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
<key>Cirque.xcscheme_^#shared#^_</key> <key>Cirque.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>5</integer> <integer>4</integer>
</dict> </dict>
<key>Localize-Swift.xcscheme</key> <key>Localize-Swift.xcscheme</key>
<dict> <dict>
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
<key>Localize-Swift.xcscheme_^#shared#^_</key> <key>Localize-Swift.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>4</integer> <integer>5</integer>
</dict> </dict>
<key>Pods-1Weather.xcscheme</key> <key>Pods-1Weather.xcscheme</key>
<dict> <dict>
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
<key>XMLCoder.xcscheme_^#shared#^_</key> <key>XMLCoder.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>3</integer> <integer>6</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