Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
1
1weather
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Dmitriy Stepanets
1weather
Commits
38c8f007
Commit
38c8f007
authored
Apr 19, 2021
by
Dmitriy Stepanets
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
RadarViewController: Added layers action
parent
2764ea06
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
436 additions
and
203 deletions
+436
-203
1Weather-Icons.sketch
+0
-0
1Weather.xcodeproj/project.pbxproj
+23
-11
1Weather.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
+1
-1
1Weather/Model/RadarLayers/RadarLayer.swift
+4
-6
1Weather/Model/RadarLayers/RadarLayerType.swift
+15
-0
1Weather/Model/RadarLayers/SevereLayerType.swift
+61
-0
1Weather/Model/RadarLayers/WeatherLayerType.swift
+15
-53
1Weather/Model/Settings.swift
+6
-57
1Weather/Resources/en.lproj/Localizable.strings
+14
-0
1Weather/Storage/UserDefaultsWrapper.swift
+67
-0
1Weather/UI/View controllers/Radar/Cells/RadarLayerCell.swift
+28
-5
1Weather/UI/View controllers/Radar/Cells/RadarLayersCellFactory.swift
+22
-3
1Weather/UI/View controllers/Radar/Controls/MapLegendView.swift
+4
-4
1Weather/UI/View controllers/Radar/MapTimeControl/MapPinnedLayersView.swift
+43
-23
1Weather/UI/View controllers/Radar/RadarMapLayersController.swift
+13
-7
1Weather/UI/View controllers/Radar/RadarViewController.swift
+34
-6
1Weather/ViewModels/RadarViewModel.swift
+64
-5
Pods/Pods.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
+22
-22
No files found.
1Weather-Icons.sketch
View file @
38c8f007
No preview for this file type
1Weather.xcodeproj/project.pbxproj
View file @
38c8f007
...
...
@@ -22,6 +22,7 @@
CD1237F4255D889F00C98139
/* GradientView.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD1237F3255D889F00C98139
/* GradientView.swift */
;
};
CD15DB3D25DA6C5100024727
/* ForecastTimePeriodControl.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD15DB3C25DA6C5100024727
/* ForecastTimePeriodControl.swift */
;
};
CD15DB4225DA806C00024727
/* TodayForecastTimePeriodCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD15DB4125DA806C00024727
/* TodayForecastTimePeriodCell.swift */
;
};
CD16A17A262D81880028E74A
/* UserDefaultsWrapper.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD16A179262D81880028E74A
/* UserDefaultsWrapper.swift */
;
};
CD17C5F625D15B4400EE884E
/* TodayViewController.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD17C5F525D15B4400EE884E
/* TodayViewController.swift */
;
};
CD17C5FB25D15B6B00EE884E
/* AppCoordinator.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD17C5FA25D15B6B00EE884E
/* AppCoordinator.swift */
;
};
CD17C5FF25D15B7C00EE884E
/* TodayCoordinator.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD17C5FE25D15B7C00EE884E
/* TodayCoordinator.swift */
;
};
...
...
@@ -60,7 +61,6 @@
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 */
;
};
...
...
@@ -68,6 +68,9 @@
CD593BCF2608A50900C93428
/* ForecastHourlyCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD593BCE2608A50900C93428
/* ForecastHourlyCell.swift */
;
};
CD593BD32608BC3F00C93428
/* ForecastDayCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD593BD22608BC3F00C93428
/* ForecastDayCell.swift */
;
};
CD593BDC2608CDF100C93428
/* Date+Now.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD593BDB2608CDF100C93428
/* Date+Now.swift */
;
};
CD59E9EF262D62DA00322329
/* WeatherLayerType.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD59E9EE262D62DA00322329
/* WeatherLayerType.swift */
;
};
CD59E9F2262D630900322329
/* SevereLayerType.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD59E9F1262D630900322329
/* SevereLayerType.swift */
;
};
CD59E9F6262D639C00322329
/* RadarLayerType.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD59E9F5262D639C00322329
/* RadarLayerType.swift */
;
};
CD647D0225ED07D60034578B
/* TodayViewModel.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD647D0125ED07D60034578B
/* TodayViewModel.swift */
;
};
CD647D0625ED08050034578B
/* ViewModelProtocol.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD647D0525ED08050034578B
/* ViewModelProtocol.swift */
;
};
CD67616A262575CD0079D273
/* MapLegendGradientView.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD676169262575CD0079D273
/* MapLegendGradientView.swift */
;
};
...
...
@@ -131,7 +134,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
/* Weathe
rLayer.swift */
;
};
CDECDB052629A6600087F9F2
/*
RadarLayer.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CDECDB042629A6600087F9F2
/* Rada
rLayer.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 */
;
};
...
...
@@ -224,6 +227,7 @@
CD1237F3255D889F00C98139
/* GradientView.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
GradientView.swift
;
sourceTree
=
"<group>"
;
};
CD15DB3C25DA6C5100024727
/* ForecastTimePeriodControl.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ForecastTimePeriodControl.swift
;
sourceTree
=
"<group>"
;
};
CD15DB4125DA806C00024727
/* TodayForecastTimePeriodCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TodayForecastTimePeriodCell.swift
;
sourceTree
=
"<group>"
;
};
CD16A179262D81880028E74A
/* UserDefaultsWrapper.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
UserDefaultsWrapper.swift
;
sourceTree
=
"<group>"
;
};
CD17C5F525D15B4400EE884E
/* TodayViewController.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TodayViewController.swift
;
sourceTree
=
"<group>"
;
};
CD17C5FA25D15B6B00EE884E
/* AppCoordinator.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
AppCoordinator.swift
;
sourceTree
=
"<group>"
;
};
CD17C5FE25D15B7C00EE884E
/* TodayCoordinator.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TodayCoordinator.swift
;
sourceTree
=
"<group>"
;
};
...
...
@@ -262,7 +266,6 @@
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>"
;
};
...
...
@@ -270,6 +273,9 @@
CD593BCE2608A50900C93428
/* ForecastHourlyCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ForecastHourlyCell.swift
;
sourceTree
=
"<group>"
;
};
CD593BD22608BC3F00C93428
/* ForecastDayCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ForecastDayCell.swift
;
sourceTree
=
"<group>"
;
};
CD593BDB2608CDF100C93428
/* Date+Now.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
"Date+Now.swift"
;
sourceTree
=
"<group>"
;
};
CD59E9EE262D62DA00322329
/* WeatherLayerType.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
WeatherLayerType.swift
;
sourceTree
=
"<group>"
;
};
CD59E9F1262D630900322329
/* SevereLayerType.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
SevereLayerType.swift
;
sourceTree
=
"<group>"
;
};
CD59E9F5262D639C00322329
/* RadarLayerType.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
RadarLayerType.swift
;
sourceTree
=
"<group>"
;
};
CD647D0125ED07D60034578B
/* TodayViewModel.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TodayViewModel.swift
;
sourceTree
=
"<group>"
;
};
CD647D0525ED08050034578B
/* ViewModelProtocol.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ViewModelProtocol.swift
;
sourceTree
=
"<group>"
;
};
CD676169262575CD0079D273
/* MapLegendGradientView.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MapLegendGradientView.swift
;
sourceTree
=
"<group>"
;
};
...
...
@@ -333,7 +339,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
=
Weathe
rLayer.swift
;
sourceTree
=
"<group>"
;
};
CDECDB042629A6600087F9F2
/*
RadarLayer.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Rada
rLayer.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>"
;
};
...
...
@@ -898,13 +904,15 @@
path
=
Forecast
;
sourceTree
=
"<group>"
;
};
CDECDB022629A5F50087F9F2
/*
Weathe
rLayers */
=
{
CDECDB022629A5F50087F9F2
/*
Rada
rLayers */
=
{
isa
=
PBXGroup
;
children
=
(
CD524E342629A120002881E2
/* WeatherLayers.swift */
,
CDECDB042629A6600087F9F2
/* WeatherLayer.swift */
,
CDECDB042629A6600087F9F2
/* RadarLayer.swift */
,
CD59E9F5262D639C00322329
/* RadarLayerType.swift */
,
CD59E9EE262D62DA00322329
/* WeatherLayerType.swift */
,
CD59E9F1262D630900322329
/* SevereLayerType.swift */
,
);
path
=
Weathe
rLayers
;
path
=
Rada
rLayers
;
sourceTree
=
"<group>"
;
};
CE28474C261597EB006C8DC5
/* Health */
=
{
...
...
@@ -1017,7 +1025,7 @@
CEAFF08125DFC66F00DF4EBF
/* Model */
=
{
isa
=
PBXGroup
;
children
=
(
CDECDB022629A5F50087F9F2
/*
Weathe
rLayers */
,
CDECDB022629A5F50087F9F2
/*
Rada
rLayers */
,
CEAFF09125DFC71D00DF4EBF
/* HelperTypes.swift */
,
CEDE4F0925EFA376007457E9
/* Protocols */
,
CEAFF0A025E0FEF100DF4EBF
/* ModelObjects */
,
...
...
@@ -1126,6 +1134,7 @@
isa
=
PBXGroup
;
children
=
(
CEFB857126174F7A00C5CDD2
/* Storage.swift */
,
CD16A179262D81880028E74A
/* UserDefaultsWrapper.swift */
,
CEFB8577261750DF00C5CDD2
/* CoreData */
,
);
path
=
Storage
;
...
...
@@ -1348,6 +1357,7 @@
CDA5542825EF734200A2E08C
/* TodayCellFactory.swift in Sources */
,
CE9F01CC261C9A6E009BA500
/* AppData.swift in Sources */
,
CEF959742600C3A400975FAA
/* FlurryAnalyticsService.swift in Sources */
,
CD59E9F6262D639C00322329
/* RadarLayerType.swift in Sources */
,
CE2847602615A8AD006C8DC5
/* BlendHealthSource.swift in Sources */
,
CD86C22225F0DCCB00F38A16
/* PrecipitationView.swift in Sources */
,
CE8962AD26175DF500CA274A
/* CoreHealth.swift in Sources */
,
...
...
@@ -1363,10 +1373,10 @@
CD1DDD332602305200AC62B2
/* ForecastInfoCell.swift in Sources */
,
CEDE4E8425EEFD56007457E9
/* WdtDailySummariesArray.swift in Sources */
,
CDEE8AD725DA882200C289DE
/* ForecastPeriodButton.swift in Sources */
,
CD59E9EF262D62DA00322329
/* WeatherLayerType.swift in Sources */
,
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 */
,
...
...
@@ -1425,6 +1435,8 @@
CD822FFE25D6976F00A05501
/* TodayAdCell.swift in Sources */
,
CEF959A626035A2600975FAA
/* DeviceLocationMonitor.swift in Sources */
,
CD32CDFF260B2E5400235081
/* ForecastDescriptionView.swift in Sources */
,
CD59E9F2262D630900322329
/* SevereLayerType.swift in Sources */
,
CD16A17A262D81880028E74A
/* UserDefaultsWrapper.swift in Sources */
,
CEC5275D25E8E50B00DA58A5
/* WdtDailySummary.swift in Sources */
,
CE9F01B8261B2DB6009BA500
/* _CoreAppData.swift in Sources */
,
CDE18DCD25D1666700C80ED9
/* ForecastCoordinator.swift in Sources */
,
...
...
@@ -1444,7 +1456,7 @@
CDF8F12D26208E7B00DB384A
/* MapCurrentTimeView.swift in Sources */
,
CEAFF08325DFC67F00DF4EBF
/* Location.swift in Sources */
,
87C171EC25FF79CC00DA3464
/* EnvironmentManager.swift in Sources */
,
CDECDB052629A6600087F9F2
/*
Weathe
rLayer.swift in Sources */
,
CDECDB052629A6600087F9F2
/*
Rada
rLayer.swift in Sources */
,
CEFB857226174F7A00C5CDD2
/* Storage.swift in Sources */
,
CD82300725D6A73F00A05501
/* TodayConditionButton.swift in Sources */
,
CDC6126A25E90C8800188DA7
/* GraphLineSettings.swift in Sources */
,
...
...
1Weather.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
View file @
38c8f007
...
...
@@ -7,7 +7,7 @@
<
k
e
y
>
1Weather.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
24
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
11
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
1.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
1Weather/Model/
WeatherLayers/Weathe
rLayer.swift
→
1Weather/Model/
RadarLayers/Rada
rLayer.swift
View file @
38c8f007
//
//
Weathe
rLayer.swift
//
Rada
rLayer.swift
// 1Weather
//
// Created by Dmitry Stepanets on 16.04.2021.
...
...
@@ -7,9 +7,7 @@
import
UIKit
struct
WeatherLayer
{
var
pinned
:
Bool
var
name
:
String
var
legendColors
:[
CGColor
]
var
values
:[
String
]
struct
RadarLayer
{
var
pinned
=
false
let
layer
:
RadarLayerType
}
1Weather/Model/RadarLayers/RadarLayerType.swift
0 → 100644
View file @
38c8f007
//
// RadarLayerProtocol.swift
// 1Weather
//
// Created by Dmitry Stepanets on 19.04.2021.
//
import
UIKit
protocol
RadarLayerType
{
var
id
:
String
{
get
}
var
name
:
String
{
get
}
var
values
:[
String
]
{
get
}
var
colors
:[
CGColor
]
{
get
}
}
1Weather/Model/RadarLayers/SevereLayerType.swift
0 → 100644
View file @
38c8f007
//
// SevereLayerType.swift
// 1Weather
//
// Created by Dmitry Stepanets on 19.04.2021.
//
import
UIKit
public
enum
SevereLayerType
:
String
,
CaseIterable
,
RadarLayerType
{
case
fire
=
"radar.severeLayer.fire"
case
floods
=
"radar.severeLayer.floods"
case
fog
=
"radar.severeLayer.fog"
case
freezing
=
"radar.severeLayer.freezing"
case
hurricaneTropical
=
"radar.severeLayer.hurricaneTropical"
case
hurricaneTropicalTracks
=
"radar.severeLayer.hurricaneTropicalTracks"
case
ice
=
"radar.severeLayer.ice"
case
snow
=
"radar.severeLayer.snow"
case
stormTornados
=
"radar.severeLayer.stormTornados"
case
wind
=
"radar.severeLayer.wind"
case
winter
=
"radar.severeLayer.winter"
var
id
:
String
{
return
self
.
rawValue
}
var
name
:
String
{
return
self
.
rawValue
.
localized
()
}
var
values
:[
String
]
{
switch
self
{
case
.
fire
:
return
[
"Watch"
,
"Warning"
]
case
.
floods
:
return
[
"Flash warn."
,
"Flash watch"
,
"Flood warn."
]
case
.
fog
:
return
[
"Freezing adv."
,
"Dense adv."
]
case
.
freezing
:
return
[
"Freezing warn."
,
"Frost adv."
,
"Frost warn."
]
case
.
hurricaneTropical
:
return
[
"Warning"
,
"Watch"
,
"Tropical warn."
,
"Tropical watch"
]
case
.
hurricaneTropicalTracks
:
return
[
"Forecast track"
,
"Past track"
,
"Forecast cone"
,
"Hurricane"
,
"Tropical storm"
,
"Low"
,
"Invest area"
]
case
.
ice
:
return
[
"Strom warn."
,
"Storm watch"
,
"Sleet warn."
,
"Sleet adv."
,
"Freezing rain adv."
]
case
.
snow
:
return
[
"Heavy snow warn."
,
"Snow adv."
,
"Blowing snow warn."
,
"Blowing snow adv."
]
case
.
stormTornados
:
return
[
"Tornado warn."
,
"Tornado watch"
,
"Severe T-Storm warn."
,
"Severe T-storm watch"
]
case
.
wind
:
return
[
"High wind warn."
,
"High wind adv."
,
"High wind watch"
,
"Wind adv."
,
"Dust strom warn."
,
"Blowing dust adv."
]
case
.
winter
:
return
[
"Blizzard warn."
,
"Blizzard watch"
,
"Winter strom warn."
,
"Winter storm watch"
,
"Winter weather adv."
]
}
}
var
colors
:[
CGColor
]
{
return
[
UIColor
.
blue
,
UIColor
.
yellow
]
.
map
{
$0
.
cgColor
}
}
}
1Weather/Model/
WeatherLayers/WeatherLayers
.swift
→
1Weather/Model/
RadarLayers/WeatherLayerType
.swift
View file @
38c8f007
//
// WeatherLayer
s
.swift
// WeatherLayer
Type
.swift
// 1Weather
//
// Created by Dmitry Stepanets on 1
6
.04.2021.
// Created by Dmitry Stepanets on 1
9
.04.2021.
//
import
UIKit
private
enum
WeatherLayerType
:
CaseIterable
{
case
radar
case
clouds
case
surfaceTemp
case
dewPoint
case
relativeHumidity
case
windSpeed
case
uvIndex
public
enum
WeatherLayerType
:
String
,
CaseIterable
,
RadarLayerType
{
case
radar
=
"radar.weatherLayer.radar"
case
clouds
=
"radar.weatherLayer.clouds"
case
surfaceTemp
=
"radar.weatherLayer.surfaceTemp"
case
dewPoint
=
"radar.weatherLayer.dewPoint"
case
relativeHumidity
=
"radar.weatherLayer.relativeHumidity"
case
windSpeed
=
"radar.weatherLayer.windSpeed"
case
uvIndex
=
"radar.weatherLayer.uvIndex"
var
id
:
String
{
return
self
.
rawValue
}
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
()
}
return
self
.
rawValue
.
localized
()
}
var
values
:[
String
]
{
...
...
@@ -110,30 +99,3 @@ private enum WeatherLayerType:CaseIterable {
}
}
}
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
{
}
1Weather/Model/Settings.swift
View file @
38c8f007
...
...
@@ -8,63 +8,6 @@
import
UIKit
import
Localize_Swift
@propertyWrapper
struct
UserDefaultsUnitValue
<
T
>
{
var
wrappedValue
:
T
{
get
{
guard
let
data
=
UserDefaults
.
standard
.
data
(
forKey
:
key
),
let
decoded
=
NSKeyedUnarchiver
.
unarchiveObject
(
with
:
data
)
as?
T
else
{
return
defaultValue
}
return
decoded
}
set
{
let
data
=
NSKeyedArchiver
.
archivedData
(
withRootObject
:
newValue
)
UserDefaults
.
standard
.
set
(
data
,
forKey
:
key
)
UserDefaults
.
standard
.
synchronize
()
Settings
.
shared
.
delegate
.
invoke
{
(
delegate
)
in
delegate
.
settingsDidChange
()
}
}
}
private
let
key
:
String
private
let
defaultValue
:
T
init
(
wrappedValue
defaultValue
:
T
,
key
:
String
)
{
self
.
defaultValue
=
defaultValue
self
.
key
=
key
}
}
@propertyWrapper
struct
UserDefaultsBasicValue
<
T
>
{
var
wrappedValue
:
T
{
get
{
let
value
=
UserDefaults
.
standard
.
value
(
forKey
:
key
)
as?
T
return
value
??
defaultValue
}
set
{
UserDefaults
.
standard
.
setValue
(
newValue
,
forKey
:
key
)
UserDefaults
.
standard
.
synchronize
()
}
}
private
let
key
:
String
private
let
defaultValue
:
T
init
(
wrappedValue
defaultValue
:
T
,
key
:
String
)
{
self
.
defaultValue
=
defaultValue
self
.
key
=
key
}
}
protocol
SettingsDelegate
:
class
{
func
settingsDidChange
()
}
...
...
@@ -116,4 +59,10 @@ class Settings {
public
var
locale
:
Locale
{
return
Locale
(
identifier
:
Localize
.
currentLanguage
())
}
@UserDefaultsBasicValue(key: "pinnedLayers")
public
var
pinnedLayerIds
:[
String
]
=
[]
@UserDefaultsBasicValue(key: "selectedLayer")
public
var
selectedLayerId
:
String
=
WeatherLayerType
.
radar
.
rawValue
}
1Weather/Resources/en.lproj/Localizable.strings
View file @
38c8f007
...
...
@@ -121,6 +121,7 @@
//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";
...
...
@@ -129,6 +130,19 @@
"radar.weatherLayer.windSpeed" = "Wind Speed";
"radar.weatherLayer.uvIndex" = "UV Index";
"radar.severeLayer.fire" = "Fire";
"radar.severeLayer.floods" = "Floods";
"radar.severeLayer.fog" = "Fog";
"radar.severeLayer.freezing" = "Freezing";
"radar.severeLayer.hurricaneTropical" = "Hurricane and tropical";
"radar.severeLayer.hurricaneTropicalTracks" = "Hurricane and tropical tracks";
"radar.severeLayer.ice" = "Ice";
"radar.severeLayer.snow" = "Snow";
"radar.severeLayer.stormTornados" = "Strorm and tornados";
"radar.severeLayer.wind" = "Wind";
"radar.severeLayer.winter" = "Winter";
//Menu
"menu.goPremium" = "Go premium";
"menu.premium.desc" = "Experience app without ads @ $8.99 a year";
...
...
1Weather/Storage/UserDefaultsWrapper.swift
0 → 100644
View file @
38c8f007
//
// UserDefaultsWrapper.swift
// 1Weather
//
// Created by Dmitry Stepanets on 19.04.2021.
//
import
Foundation
@propertyWrapper
struct
UserDefaultsUnitValue
<
T
>
{
var
wrappedValue
:
T
{
get
{
guard
let
data
=
UserDefaults
.
standard
.
data
(
forKey
:
key
),
let
decoded
=
NSKeyedUnarchiver
.
unarchiveObject
(
with
:
data
)
as?
T
else
{
return
defaultValue
}
return
decoded
}
set
{
let
data
=
NSKeyedArchiver
.
archivedData
(
withRootObject
:
newValue
)
UserDefaults
.
standard
.
set
(
data
,
forKey
:
key
)
UserDefaults
.
standard
.
synchronize
()
Settings
.
shared
.
delegate
.
invoke
{
(
delegate
)
in
delegate
.
settingsDidChange
()
}
}
}
private
let
key
:
String
private
let
defaultValue
:
T
init
(
wrappedValue
defaultValue
:
T
,
key
:
String
)
{
self
.
defaultValue
=
defaultValue
self
.
key
=
key
}
}
@propertyWrapper
struct
UserDefaultsBasicValue
<
T
>
{
var
wrappedValue
:
T
{
get
{
let
value
=
UserDefaults
.
standard
.
value
(
forKey
:
key
)
as?
T
return
value
??
defaultValue
}
set
{
UserDefaults
.
standard
.
setValue
(
newValue
,
forKey
:
key
)
UserDefaults
.
standard
.
synchronize
()
}
}
private
let
key
:
String
private
let
defaultValue
:
T
init
(
wrappedValue
defaultValue
:
T
,
key
:
String
)
{
self
.
defaultValue
=
defaultValue
self
.
key
=
key
}
}
1Weather/UI/View controllers/Radar/Cells/RadarLayerCell.swift
View file @
38c8f007
...
...
@@ -7,10 +7,18 @@
import
UIKit
protocol
RadarLayerCellDelegate
:
class
{
func
cellPinButtonTouched
(
atLayer
:
RadarLayer
)
}
class
RadarLayerCell
:
UITableViewCell
{
//Private
private
let
nameLabel
=
UILabel
()
private
let
pinButton
=
UIButton
()
private
var
currentRadarLayer
:
RadarLayer
?
//Public
weak
var
delegate
:
RadarLayerCellDelegate
?
override
init
(
style
:
UITableViewCell
.
CellStyle
,
reuseIdentifier
:
String
?)
{
super
.
init
(
style
:
style
,
reuseIdentifier
:
reuseIdentifier
)
...
...
@@ -21,12 +29,23 @@ class RadarLayerCell: UITableViewCell {
updateUI
()
}
override
var
isSelected
:
Bool
{
didSet
{
contentView
.
backgroundColor
=
isSelected
?
ThemeManager
.
currentTheme
.
graphTintColor
.
withAlphaComponent
(
0.2
)
:
ThemeManager
.
currentTheme
.
baseBackgroundColor
}
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
public
func
configure
(
weatherLayer
:
WeatherLayer
)
{
nameLabel
.
text
=
weatherLayer
.
name
public
func
configure
(
radarLayer
:
RadarLayer
)
{
self
.
currentRadarLayer
=
radarLayer
nameLabel
.
text
=
radarLayer
.
layer
.
name
nameLabel
.
font
=
radarLayer
.
pinned
?
AppFont
.
SFPro
.
bold
(
size
:
14
)
:
AppFont
.
SFPro
.
regular
(
size
:
14
)
pinButton
.
backgroundColor
=
radarLayer
.
pinned
?
UIColor
.
black
:
UIColor
(
hex
:
0x242B2E
)
.
withAlphaComponent
(
0.57
)
pinButton
.
tintColor
=
radarLayer
.
pinned
?
UIColor
.
white
:
UIColor
(
hex
:
0xD9D9D9
)
}
override
func
traitCollectionDidChange
(
_
previousTraitCollection
:
UITraitCollection
?)
{
...
...
@@ -44,7 +63,11 @@ class RadarLayerCell: UITableViewCell {
}
@objc
private
func
handlePinButton
()
{
guard
let
layer
=
currentRadarLayer
else
{
return
}
self
.
nameLabel
.
font
=
layer
.
pinned
?
AppFont
.
SFPro
.
bold
(
size
:
14
)
:
AppFont
.
SFPro
.
regular
(
size
:
14
)
self
.
pinButton
.
backgroundColor
=
!
layer
.
pinned
?
UIColor
.
black
:
UIColor
(
hex
:
0x242B2E
)
.
withAlphaComponent
(
0.57
)
self
.
pinButton
.
tintColor
=
!
layer
.
pinned
?
UIColor
.
white
:
UIColor
(
hex
:
0xD9D9D9
)
self
.
delegate
?
.
cellPinButtonTouched
(
atLayer
:
layer
)
}
}
...
...
@@ -56,14 +79,14 @@ private extension RadarLayerCell {
}
func
prepareNameLabel
()
{
nameLabel
.
lineBreakMode
=
.
byTruncating
Tail
nameLabel
.
lineBreakMode
=
.
byTruncating
Middle
nameLabel
.
font
=
AppFont
.
SFPro
.
regular
(
size
:
14
)
contentView
.
addSubview
(
nameLabel
)
nameLabel
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
equalToSuperview
()
.
inset
(
15
)
make
.
centerY
.
equalToSuperview
()
make
.
right
.
equalTo
(
pinButton
.
snp
.
left
)
.
inset
(
8
)
.
priority
(
999
)
make
.
right
.
equalTo
(
pinButton
.
snp
.
left
)
.
offset
(
-
8
)
.
priority
(
999
)
}
}
...
...
1Weather/UI/View controllers/Radar/Cells/RadarLayersCellFactory.swift
View file @
38c8f007
...
...
@@ -25,7 +25,7 @@ class RadarLayersCellFactory: CellFactoryProtocol {
init
(
radarViewModel
:
RadarViewModel
)
{
self
.
radarViewModel
=
radarViewModel
sections
=
[
LayerSection
(
type
:
.
weather
,
rowsCount
:
radarViewModel
.
weatherLayers
.
count
),
LayerSection
(
type
:
.
severe
,
rowsCount
:
0
)]
LayerSection
(
type
:
.
severe
,
rowsCount
:
radarViewModel
.
severeLayers
.
count
)]
}
var
numberOfSections
:
Int
{
...
...
@@ -42,13 +42,32 @@ class RadarLayersCellFactory: CellFactoryProtocol {
func
cellFromTableView
(
tableView
:
UITableView
,
indexPath
:
IndexPath
)
->
UITableViewCell
{
let
cell
=
dequeueReusableCell
(
type
:
RadarLayerCell
.
self
,
tableView
:
tableView
,
indexPath
:
indexPath
)
cell
.
delegate
=
self
switch
sections
[
indexPath
.
section
]
.
type
{
case
.
weather
:
cell
.
configure
(
weatherLayer
:
radarViewModel
.
weatherLayers
[
indexPath
.
row
])
cell
.
configure
(
radarLayer
:
radarViewModel
.
weatherLayers
[
indexPath
.
row
])
cell
.
isSelected
=
radarViewModel
.
weatherLayers
[
indexPath
.
row
]
.
layer
.
id
==
radarViewModel
.
selectedLayer
?
.
layer
.
id
case
.
severe
:
break
cell
.
configure
(
radarLayer
:
radarViewModel
.
severeLayers
[
indexPath
.
row
])
cell
.
isSelected
=
radarViewModel
.
severeLayers
[
indexPath
.
row
]
.
layer
.
id
==
radarViewModel
.
selectedLayer
?
.
layer
.
id
}
return
cell
}
func
didSelectRow
(
indexPath
:
IndexPath
)
{
switch
sections
[
indexPath
.
section
]
.
type
{
case
.
weather
:
radarViewModel
.
select
(
layer
:
radarViewModel
.
weatherLayers
[
indexPath
.
row
])
case
.
severe
:
radarViewModel
.
select
(
layer
:
radarViewModel
.
severeLayers
[
indexPath
.
row
])
}
}
}
//MARK:- RadarLayer cell delegate
extension
RadarLayersCellFactory
:
RadarLayerCellDelegate
{
func
cellPinButtonTouched
(
atLayer
:
RadarLayer
)
{
radarViewModel
.
updatePinnedState
(
forLayer
:
atLayer
)
}
}
1Weather/UI/View controllers/Radar/Controls/MapLegendView.swift
View file @
38c8f007
...
...
@@ -48,12 +48,12 @@ class MapLegendView: UIView {
}
//Public
public
func
configure
(
weatherLayer
:
Weathe
rLayer
)
{
legendGradient
.
set
(
colors
:
weatherLayer
.
legendC
olors
)
buttonGradient
.
colors
=
weatherLayer
.
legendC
olors
public
func
configure
(
radarLayer
:
Rada
rLayer
)
{
legendGradient
.
set
(
colors
:
radarLayer
.
layer
.
c
olors
)
buttonGradient
.
colors
=
radarLayer
.
layer
.
c
olors
legendLabelsStackView
.
removeAll
()
weatherL
ayer
.
values
.
enumerated
()
.
forEach
{
radarLayer
.
l
ayer
.
values
.
enumerated
()
.
forEach
{
let
label
=
UILabel
()
label
.
font
=
AppFont
.
SFPro
.
regular
(
size
:
10
)
label
.
text
=
$1
...
...
1Weather/UI/View controllers/Radar/MapTimeControl/MapPinnedLayersView.swift
View file @
38c8f007
...
...
@@ -7,6 +7,10 @@
import
UIKit
protocol
MapPinnedLayersViewDelegate
:
class
{
func
didSelectLayer
(
layerId
:
String
)
}
class
MapPinnedLayersView
:
UIView
{
//Private
private
let
pinContainer
=
UIView
()
...
...
@@ -14,6 +18,12 @@ class MapPinnedLayersView: UIView {
private
let
scrollView
=
UIScrollView
()
private
let
stackView
=
UIStackView
()
//Public
weak
var
delegate
:
MapPinnedLayersViewDelegate
?
public
var
isEmpty
:
Bool
{
return
stackView
.
arrangedSubviews
.
count
<
2
}
init
()
{
super
.
init
(
frame
:
.
zero
)
...
...
@@ -21,16 +31,6 @@ class MapPinnedLayersView: UIView {
prepareScrollView
()
prepareStackView
()
updateUI
()
for
index
in
0
..<
6
{
let
button
=
PinnedlLayerButton
(
name
:
"Temperature"
)
button
.
isSelected
=
index
==
0
if
index
==
5
{
button
.
configureForAdd
()
}
stackView
.
addArrangedSubview
(
button
)
}
stackView
.
layoutIfNeeded
()
}
required
init
?(
coder
:
NSCoder
)
{
...
...
@@ -43,27 +43,40 @@ class MapPinnedLayersView: UIView {
}
//Public
public
func
setPinnedLayers
(
layers
:[
Weathe
rLayer
])
{
public
func
setPinnedLayers
(
layers
:[
Rada
rLayer
])
{
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
)
}
//Add button
let
addButton
=
PinnedlLayerButton
()
addButton
.
configureForAdd
()
addButton
.
addTarget
(
self
,
action
:
#selector(
handleLayerButton(button:)
)
,
for
:
.
touchUpInside
)
stackView
.
addArrangedSubview
(
addButton
)
layers
.
forEach
{
let
button
=
PinnedlLayerButton
(
radarLayer
:
$0
)
button
.
isSelected
=
false
button
.
addTarget
(
self
,
action
:
#selector(
handleLayerButton(button:)
)
,
for
:
.
touchUpInside
)
stackView
.
insertArrangedSubview
(
button
,
at
:
0
)
}
stackView
.
layoutIfNeeded
()
}
public
func
selectLayer
(
radarLayer
:
RadarLayer
)
{
stackView
.
arrangedSubviews
.
forEach
{
if
let
layerButton
=
$0
as?
PinnedlLayerButton
{
layerButton
.
isSelected
=
radarLayer
.
layer
.
id
==
layerButton
.
layerId
}
}
}
//Private
private
func
updateUI
()
{
self
.
backgroundColor
=
ThemeManager
.
currentTheme
.
containerBackgroundColor
}
@objc
private
func
handleLayerButton
(
button
:
PinnedlLayerButton
)
{
delegate
?
.
didSelectLayer
(
layerId
:
button
.
layerId
)
}
}
//MARK:- Prepare Pinned Layers
...
...
@@ -123,13 +136,19 @@ private extension MapPinnedLayersView {
//MARK:- PinnedLayer Button
private
class
PinnedlLayerButton
:
UIControl
{
//Private
private
let
gradient
=
CAGradientLayer
()
private
let
nameLabel
=
UILabel
()
private
var
configuredForAdd
=
false
init
(
name
:
String
)
{
//Public
let
layerId
:
String
init
(
radarLayer
:
RadarLayer
?
=
nil
)
{
self
.
layerId
=
radarLayer
?
.
layer
.
id
??
""
super
.
init
(
frame
:
.
zero
)
nameLabel
.
text
=
name
nameLabel
.
text
=
radarLayer
?
.
layer
.
name
prepareView
()
prepareGradient
()
...
...
@@ -183,6 +202,7 @@ private class PinnedlLayerButton: UIControl {
self
.
layer
.
borderWidth
=
1
self
.
nameLabel
.
textColor
=
ThemeManager
.
currentTheme
.
graphTintColor
self
.
nameLabel
.
text
=
"general.add"
.
localized
()
.
capitalized
+
" +"
self
.
isSelected
=
false
self
.
configuredForAdd
=
true
}
...
...
1Weather/UI/View controllers/Radar/RadarMapLayersController.swift
View file @
38c8f007
...
...
@@ -29,13 +29,13 @@ class RadarMapLayersController: UIViewController {
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
view
.
backgroundColor
=
UIColor
.
black
.
withAlphaComponent
(
0.5
)
prepareController
(
)
prepareTableView
()
}
override
func
viewDidLayoutSubviews
()
{
super
.
viewDidLayoutSubviews
()
self
.
tableV
iew
.
layer
.
shadowPath
=
CGPath
(
rect
:
self
.
view
.
bounds
,
transform
:
nil
)
self
.
v
iew
.
layer
.
shadowPath
=
CGPath
(
rect
:
self
.
view
.
bounds
,
transform
:
nil
)
}
@objc
private
func
handleCloseButton
()
{
...
...
@@ -46,16 +46,17 @@ class RadarMapLayersController: UIViewController {
//MARK:- Prepare
private
extension
RadarMapLayersController
{
func
prepareController
()
{
view
.
clipsToBounds
=
false
view
.
backgroundColor
=
.
black
view
.
layer
.
shadowColor
=
UIColor
.
black
.
withAlphaComponent
(
0.12
)
.
cgColor
view
.
layer
.
shadowRadius
=
8
view
.
layer
.
shadowOffset
=
.
init
(
width
:
0
,
height
:
3
)
view
.
layer
.
shadowOpacity
=
1
}
func
prepareTableView
()
{
cellFactory
.
registerCells
(
on
:
tableView
)
tableView
.
clipsToBounds
=
false
tableView
.
layer
.
shadowColor
=
UIColor
.
black
.
withAlphaComponent
(
0.12
)
.
cgColor
tableView
.
layer
.
shadowRadius
=
8
tableView
.
layer
.
shadowOffset
=
.
init
(
width
:
0
,
height
:
3
)
tableView
.
layer
.
shadowOpacity
=
1
tableView
.
backgroundColor
=
ThemeManager
.
currentTheme
.
baseBackgroundColor
tableView
.
tableHeaderView
=
UIView
(
frame
:
.
init
(
origin
:
.
zero
,
size
:
CGSize
(
width
:
0
,
height
:
0.01
)))
tableView
.
dataSource
=
self
...
...
@@ -151,6 +152,11 @@ extension RadarMapLayersController: UITableViewDelegate {
return
container
}
func
tableView
(
_
tableView
:
UITableView
,
didSelectRowAt
indexPath
:
IndexPath
)
{
cellFactory
.
didSelectRow
(
indexPath
:
indexPath
)
tableView
.
reloadData
()
}
}
//MARK:- Transitioning Delegate
...
...
1Weather/UI/View controllers/Radar/RadarViewController.swift
View file @
38c8f007
...
...
@@ -55,9 +55,7 @@ class RadarViewController: UIViewController {
prepareMapButtons
()
prepareMapTimeControl
()
updateUI
()
centerMap
()
cityButton
.
configure
(
with
:
radarViewModel
.
location
)
initialConfigure
()
}
//Private
...
...
@@ -75,6 +73,17 @@ class RadarViewController: UIViewController {
mapView
.
setRegion
(
region
,
animated
:
true
)
}
private
func
initialConfigure
()
{
self
.
centerMap
()
cityButton
.
configure
(
with
:
radarViewModel
.
location
)
pinnedLayersView
.
setPinnedLayers
(
layers
:
radarViewModel
.
pinnedLayers
)
if
let
selectedLayer
=
radarViewModel
.
selectedLayer
{
legendView
.
configure
(
radarLayer
:
selectedLayer
)
pinnedLayersView
.
selectLayer
(
radarLayer
:
selectedLayer
)
}
}
@objc
private
func
handleCityButton
()
{
}
...
...
@@ -161,7 +170,8 @@ private extension RadarViewController {
}
func
prepareMapPinnedLayers
()
{
pinnedLayersView
.
setPinnedLayers
(
layers
:
radarViewModel
.
weatherLayers
)
pinnedLayersView
.
delegate
=
self
pinnedLayersView
.
setPinnedLayers
(
layers
:
radarViewModel
.
pinnedLayers
)
view
.
addSubview
(
pinnedLayersView
)
pinnedLayersView
.
snp
.
makeConstraints
{
(
make
)
in
...
...
@@ -182,7 +192,6 @@ private extension RadarViewController {
}
//Legend
legendView
.
configure
(
weatherLayer
:
radarViewModel
.
weatherLayers
[
6
])
view
.
addSubview
(
legendView
)
legendView
.
snp
.
makeConstraints
{
(
make
)
in
make
.
right
.
equalToSuperview
()
.
inset
(
8
)
...
...
@@ -233,9 +242,28 @@ private extension RadarViewController {
}
//MARK:- ViewModel Delegate
extension
RadarViewController
:
ViewModelDelegate
{
extension
RadarViewController
:
Radar
ViewModelDelegate
{
func
viewModelDidChange
<
P
>
(
model
:
P
)
where
P
:
ViewModelProtocol
{
self
.
centerMap
()
cityButton
.
configure
(
with
:
radarViewModel
.
location
)
}
func
viewModel
(
model
:
RadarViewModel
,
didSelectLayer
layer
:
RadarLayer
)
{
pinnedLayersView
.
selectLayer
(
radarLayer
:
layer
)
legendView
.
configure
(
radarLayer
:
layer
)
}
func
viewModelPinnedLayersDidChange
(
model
:
RadarViewModel
)
{
pinnedLayersView
.
setPinnedLayers
(
layers
:
radarViewModel
.
pinnedLayers
)
if
let
selectedLayer
=
radarViewModel
.
selectedLayer
{
pinnedLayersView
.
selectLayer
(
radarLayer
:
selectedLayer
)
}
}
}
//MARK:- PinnedLayersView Delegate
extension
RadarViewController
:
MapPinnedLayersViewDelegate
{
func
didSelectLayer
(
layerId
:
String
)
{
radarViewModel
.
select
(
layerId
:
layerId
)
}
}
1Weather/ViewModels/RadarViewModel.swift
View file @
38c8f007
...
...
@@ -7,14 +7,31 @@
import
UIKit
protocol
RadarViewModelDelegate
:
ViewModelDelegate
{
func
viewModel
(
model
:
RadarViewModel
,
didSelectLayer
layer
:
RadarLayer
)
func
viewModelPinnedLayersDidChange
(
model
:
RadarViewModel
)
}
class
RadarViewModel
:
ViewModelProtocol
{
//Public
public
weak
var
delegate
:
ViewModelDelegate
?
public
var
weatherLayers
:[
WeatherLayer
]
{
return
WeatherLayers
.
allLayers
public
weak
var
delegate
:
RadarViewModelDelegate
?
public
private(set)
var
weatherLayers
:[
RadarLayer
]
public
private(set)
var
severeLayers
:[
RadarLayer
]
public
var
pinnedLayers
:[
RadarLayer
]
{
return
weatherLayers
.
filter
{
$0
.
pinned
}
+
severeLayers
.
filter
{
$0
.
pinned
}
}
public
var
pinnedLayers
:[
WeatherLayer
]
{
return
WeatherLayers
.
allLayers
.
filter
{
$0
.
pinned
}
public
var
selectedLayer
:
RadarLayer
?
{
let
selectedLayerId
=
Settings
.
shared
.
selectedLayerId
if
let
weatherSelectedLayer
=
(
weatherLayers
.
first
{
$0
.
layer
.
id
==
selectedLayerId
})
{
return
weatherSelectedLayer
}
if
let
severeSelectedLayer
=
(
severeLayers
.
first
{
$0
.
layer
.
id
==
selectedLayerId
})
{
return
severeSelectedLayer
}
return
nil
}
//Private
...
...
@@ -24,8 +41,50 @@ class RadarViewModel: ViewModelProtocol {
}
init
()
{
let
pinnedLayerIds
=
Settings
.
shared
.
pinnedLayerIds
//Fill weather layers
weatherLayers
=
WeatherLayerType
.
allCases
.
map
{
RadarLayer
(
pinned
:
pinnedLayerIds
.
contains
(
$0
.
id
),
layer
:
$0
)
}
severeLayers
=
SevereLayerType
.
allCases
.
map
{
RadarLayer
(
pinned
:
pinnedLayerIds
.
contains
(
$0
.
id
),
layer
:
$0
)
}
locationManager
.
add
(
delegate
:
self
)
}
public
func
updatePinnedState
(
forLayer
layer
:
RadarLayer
)
{
//Weather
if
let
weatherIndex
=
(
weatherLayers
.
firstIndex
{
$0
.
layer
.
id
==
layer
.
layer
.
id
})
{
weatherLayers
[
weatherIndex
]
.
pinned
=
!
weatherLayers
[
weatherIndex
]
.
pinned
}
//Severe
if
let
severeIndex
=
(
severeLayers
.
firstIndex
{
$0
.
layer
.
id
==
layer
.
layer
.
id
})
{
severeLayers
[
severeIndex
]
.
pinned
=
!
severeLayers
[
severeIndex
]
.
pinned
}
//Save changes
Settings
.
shared
.
pinnedLayerIds
=
self
.
pinnedLayers
.
map
{
$0
.
layer
.
id
}
delegate
?
.
viewModelPinnedLayersDidChange
(
model
:
self
)
}
public
func
select
(
layer
:
RadarLayer
)
{
Settings
.
shared
.
selectedLayerId
=
layer
.
layer
.
id
delegate
?
.
viewModel
(
model
:
self
,
didSelectLayer
:
layer
)
}
public
func
select
(
layerId
:
String
)
{
var
layer
:
RadarLayer
?
if
let
weatherLayer
=
(
weatherLayers
.
firstIndex
{
$0
.
layer
.
id
==
layerId
})
{
layer
=
weatherLayers
[
weatherLayer
]
}
if
let
severeLayer
=
(
severeLayers
.
firstIndex
{
$0
.
layer
.
id
==
layerId
})
{
layer
=
severeLayers
[
severeLayer
]
}
guard
let
selectedLayer
=
layer
else
{
return
}
Settings
.
shared
.
selectedLayerId
=
layerId
delegate
?
.
viewModel
(
model
:
self
,
didSelectLayer
:
selectedLayer
)
}
}
//MARK:- LocationManager Delegate
...
...
Pods/Pods.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
View file @
38c8f007
...
...
@@ -14,14 +14,14 @@
<
k
e
y
>
AlgoliaSearchClient.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
20
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
7
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
BezierKit.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
1
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
0
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
Cirque.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -33,7 +33,7 @@
<
k
e
y
>
Cirque.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
18
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
3
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
Firebase.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -45,7 +45,7 @@
<
k
e
y
>
Firebase.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
1
6
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
1
8
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
FirebaseABTesting.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -57,7 +57,7 @@
<
k
e
y
>
FirebaseABTesting.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
4
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
16
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
FirebaseAnalytics.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -69,7 +69,7 @@
<
k
e
y
>
FirebaseAnalytics.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
8
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
12
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
FirebaseCore.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -81,7 +81,7 @@
<
k
e
y
>
FirebaseCore.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
1
5
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
1
7
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
FirebaseCoreDiagnostics.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -105,7 +105,7 @@
<
k
e
y
>
FirebaseCrashlytics.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
19
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
20
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
FirebaseInstallations.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -129,7 +129,7 @@
<
k
e
y
>
FirebaseRemoteConfig.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
2
3
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
2
2
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
Flurry-iOS-SDK.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -141,7 +141,7 @@
<
k
e
y
>
Flurry-iOS-SDK.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
2
4
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
4
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
GoogleAppMeasurement.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -153,7 +153,7 @@
<
k
e
y
>
GoogleAppMeasurement.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
10
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
24
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
GoogleDataTransport.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -165,7 +165,7 @@
<
k
e
y
>
GoogleDataTransport.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
5
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
21
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
GoogleUtilities.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -177,7 +177,7 @@
<
k
e
y
>
GoogleUtilities.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
3
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
10
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
Localize-Swift.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -189,7 +189,7 @@
<
k
e
y
>
Localize-Swift.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
11
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
5
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
Logging.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -201,7 +201,7 @@
<
k
e
y
>
Logging.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
1
7
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
1
5
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
MORichNotification.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -213,7 +213,7 @@
<
k
e
y
>
MORichNotification.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
7
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
19
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
MoEngage-iOS-SDK.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -225,14 +225,14 @@
<
k
e
y
>
MoEngage-iOS-SDK.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
1
3
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
1
4
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
Pods-1Weather.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
2
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
1
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PromisesObjC.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -244,14 +244,14 @@
<
k
e
y
>
PromisesObjC.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
2
1
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
2
3
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
SnapKit.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
4
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
2
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
XMLCoder.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -263,7 +263,7 @@
<
k
e
y
>
XMLCoder.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
14
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
8
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
nanopb.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -275,7 +275,7 @@
<
k
e
y
>
nanopb.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
1
2
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
1
3
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
/
d
i
c
t
>
<
k
e
y
>
SuppressBuildableAutocreation
<
/k
e
y
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment