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
867a91f2
Commit
867a91f2
authored
Apr 13, 2021
by
Dmitriy Stepanets
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Finished RadarController UI
parent
2d2dd5f8
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
714 additions
and
57 deletions
+714
-57
1Weather-Icons.sketch
+0
-0
1Weather.xcodeproj/project.pbxproj
+48
-0
1Weather.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
+1
-1
1Weather/Extensions/UITabBarController+Hide.swift
+67
-0
1Weather/Resources/Assets.xcassets/map_legend_close.imageset/Contents.json
+16
-0
1Weather/Resources/Assets.xcassets/map_legend_close.imageset/map_legend_close.pdf
+0
-0
1Weather/Resources/Assets.xcassets/radar_layer_pin.imageset/Contents.json
+16
-0
1Weather/Resources/Assets.xcassets/radar_layer_pin.imageset/radar_layer_pin.pdf
+0
-0
1Weather/Resources/en.lproj/Localizable.strings
+4
-0
1Weather/UI/View controllers/Radar/Animators/MapLayersDismissAnimator.swift
+28
-0
1Weather/UI/View controllers/Radar/Animators/MapLayersPresentationAnimator.swift
+33
-0
1Weather/UI/View controllers/Radar/Cells/RadarLayerCell.swift
+84
-0
1Weather/UI/View controllers/Radar/Cells/RadarLayersCellFactory.swift
+42
-0
1Weather/UI/View controllers/Radar/Controls/MapButton.swift
+12
-13
1Weather/UI/View controllers/Radar/Controls/MapLegendGradientView.swift
+39
-0
1Weather/UI/View controllers/Radar/Controls/MapLegendView.swift
+47
-9
1Weather/UI/View controllers/Radar/MapTimeControl/MapPinnedLayersView.swift
+2
-2
1Weather/UI/View controllers/Radar/RadarMapLayersController.swift
+161
-0
1Weather/UI/View controllers/Radar/RadarViewController.swift
+54
-10
1Weather/ViewModels/RadarViewModel.swift
+36
-0
1Weather/ViewModels/TodayViewModel.swift
+2
-0
Pods/Pods.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
+22
-22
No files found.
1Weather-Icons.sketch
View file @
867a91f2
No preview for this file type
1Weather.xcodeproj/project.pbxproj
View file @
867a91f2
...
...
@@ -69,6 +69,14 @@
CD593BDC2608CDF100C93428
/* Date+Now.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD593BDB2608CDF100C93428
/* Date+Now.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 */
;
};
CD67616D262587D30079D273
/* UITabBarController+Hide.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD67616C262587D30079D273
/* UITabBarController+Hide.swift */
;
};
CD67617026259D220079D273
/* RadarMapLayersController.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD67616F26259D220079D273
/* RadarMapLayersController.swift */
;
};
CD67617726259DD70079D273
/* MapLayersPresentationAnimator.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD67617626259DD70079D273
/* MapLayersPresentationAnimator.swift */
;
};
CD67617C2625A60B0079D273
/* MapLayersDismissAnimator.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD67617B2625A60B0079D273
/* MapLayersDismissAnimator.swift */
;
};
CD6761802625B0F50079D273
/* RadarLayerCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD67617F2625B0F50079D273
/* RadarLayerCell.swift */
;
};
CD6761842625B6A10079D273
/* RadarLayersCellFactory.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD6761832625B6A10079D273
/* RadarLayersCellFactory.swift */
;
};
CD6761882625C3360079D273
/* RadarViewModel.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD6761872625C3360079D273
/* RadarViewModel.swift */
;
};
CD6B3036257262C2004B34B3
/* UIColor+Highlight.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD6B3035257262C2004B34B3
/* UIColor+Highlight.swift */
;
};
CD6B303B2572680C004B34B3
/* SelfSizingButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD6B303A2572680C004B34B3
/* SelfSizingButton.swift */
;
};
CD6B303E25726960004B34B3
/* ThemeProtocol.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD6B303D25726960004B34B3
/* ThemeProtocol.swift */
;
};
...
...
@@ -261,6 +269,14 @@
CD593BDB2608CDF100C93428
/* Date+Now.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
"Date+Now.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>"
;
};
CD67616C262587D30079D273
/* UITabBarController+Hide.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
"UITabBarController+Hide.swift"
;
sourceTree
=
"<group>"
;
};
CD67616F26259D220079D273
/* RadarMapLayersController.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
RadarMapLayersController.swift
;
sourceTree
=
"<group>"
;
};
CD67617626259DD70079D273
/* MapLayersPresentationAnimator.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MapLayersPresentationAnimator.swift
;
sourceTree
=
"<group>"
;
};
CD67617B2625A60B0079D273
/* MapLayersDismissAnimator.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MapLayersDismissAnimator.swift
;
sourceTree
=
"<group>"
;
};
CD67617F2625B0F50079D273
/* RadarLayerCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
RadarLayerCell.swift
;
sourceTree
=
"<group>"
;
};
CD6761832625B6A10079D273
/* RadarLayersCellFactory.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
RadarLayersCellFactory.swift
;
sourceTree
=
"<group>"
;
};
CD6761872625C3360079D273
/* RadarViewModel.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
RadarViewModel.swift
;
sourceTree
=
"<group>"
;
};
CD6B3035257262C2004B34B3
/* UIColor+Highlight.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
"UIColor+Highlight.swift"
;
sourceTree
=
"<group>"
;
};
CD6B303A2572680C004B34B3
/* SelfSizingButton.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
SelfSizingButton.swift
;
sourceTree
=
"<group>"
;
};
CD6B303D25726960004B34B3
/* ThemeProtocol.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ThemeProtocol.swift
;
sourceTree
=
"<group>"
;
};
...
...
@@ -501,6 +517,7 @@
CDC70832260FBFD3004A1974
/* UnitPressure+Atmosphere.swift */
,
CDF4808E261727E00076E9F5
/* CLAuthorizationStatus+Localized.swift */
,
CDF48091261729680076E9F5
/* UIApplication+Settings.swift */
,
CD67616C262587D30079D273
/* UITabBarController+Hide.swift */
,
);
path
=
Extensions
;
sourceTree
=
"<group>"
;
...
...
@@ -636,10 +653,29 @@
CD32CE07260C743B00235081
/* MenuViewModel.swift */
,
CD37D3F5260DF5BA002669D6
/* SettingsViewModel.swift */
,
CD866A6E260F67F200E96A5C
/* SettingsDetailsViewModel.swift */
,
CD6761872625C3360079D273
/* RadarViewModel.swift */
,
);
path
=
ViewModels
;
sourceTree
=
"<group>"
;
};
CD67617526259DBE0079D273
/* Animators */
=
{
isa
=
PBXGroup
;
children
=
(
CD67617626259DD70079D273
/* MapLayersPresentationAnimator.swift */
,
CD67617B2625A60B0079D273
/* MapLayersDismissAnimator.swift */
,
);
path
=
Animators
;
sourceTree
=
"<group>"
;
};
CD67617E2625B0DE0079D273
/* Cells */
=
{
isa
=
PBXGroup
;
children
=
(
CD67617F2625B0F50079D273
/* RadarLayerCell.swift */
,
CD6761832625B6A10079D273
/* RadarLayersCellFactory.swift */
,
);
path
=
Cells
;
sourceTree
=
"<group>"
;
};
CD6B3038257267E2004B34B3
/* View controllers */
=
{
isa
=
PBXGroup
;
children
=
(
...
...
@@ -676,9 +712,12 @@
CD7BF15026203E2300A30DF5
/* Radar */
=
{
isa
=
PBXGroup
;
children
=
(
CD67617E2625B0DE0079D273
/* Cells */
,
CD67617526259DBE0079D273
/* Animators */
,
CDAD97B726207DFE007FCFB1
/* MapTimeControl */
,
CDAD97AF26204285007FCFB1
/* Controls */
,
CD7BF15426203E6900A30DF5
/* RadarViewController.swift */
,
CD67616F26259D220079D273
/* RadarMapLayersController.swift */
,
);
path
=
Radar
;
sourceTree
=
"<group>"
;
...
...
@@ -746,6 +785,7 @@
children
=
(
CDAD97B0262042B2007FCFB1
/* MapButton.swift */
,
CD18728A2624763000AFEDAA
/* MapLegendView.swift */
,
CD676169262575CD0079D273
/* MapLegendGradientView.swift */
,
);
path
=
Controls
;
sourceTree
=
"<group>"
;
...
...
@@ -1237,13 +1277,17 @@
87C1724925FF94F400DA3464
/* ConfigManager.swift in Sources */
,
CE9D181925ECB9A70028D9D7
/* Logger.swift in Sources */
,
CE8962AE26175DF500CA274A
/* CoreLocation.swift in Sources */
,
CD67616A262575CD0079D273
/* MapLegendGradientView.swift in Sources */
,
CE578FD325F7E89400E8B85D
/* DayTimeWeather.swift in Sources */
,
CD593BCC2608A4F200C93428
/* ForecastDailyCell.swift in Sources */
,
CEF959692600C30500975FAA
/* Global.swift in Sources */
,
CEAFF08925DFC6B200DF4EBF
/* CurrentWeather.swift in Sources */
,
CD866A72260F6A5300E96A5C
/* SettingsDetailsCell.swift in Sources */
,
CD6761802625B0F50079D273
/* RadarLayerCell.swift in Sources */
,
CEC5270325E7BB4000DA58A5
/* WdtSurfaceObservation.swift in Sources */
,
CE28474F26159857006C8DC5
/* HealthSource.swift in Sources */
,
CD6761842625B6A10079D273
/* RadarLayersCellFactory.swift in Sources */
,
CD67617C2625A60B0079D273
/* MapLayersDismissAnimator.swift in Sources */
,
CEAFF08C25DFC6BD00DF4EBF
/* DailyWeather.swift in Sources */
,
CEDE4F0B25EFA3A7007457E9
/* UpdatableModelObject.swift in Sources */
,
CE8962A626175DF500CA274A
/* _CoreHealth.swift in Sources */
,
...
...
@@ -1262,6 +1306,7 @@
CDAD97B426207D14007FCFB1
/* MapTimeControlView.swift in Sources */
,
CD32CE0E260C770E00235081
/* MenuHeaderView.swift in Sources */
,
CD15DB3D25DA6C5100024727
/* ForecastTimePeriodControl.swift in Sources */
,
CD67617726259DD70079D273
/* MapLayersPresentationAnimator.swift in Sources */
,
CD1237F1255D83C500C98139
/* UIColor+Hex.swift in Sources */
,
CD7BF1582620410800A30DF5
/* RadarCoordinator.swift in Sources */
,
CDD0F1EE25725BCF00CF5017
/* ThemeManager.swift in Sources */
,
...
...
@@ -1327,6 +1372,7 @@
CE578FE725FB415F00E8B85D
/* LocationsViewModel.swift in Sources */
,
CD82300A25D6B2AF00A05501
/* AppTabBarController.swift in Sources */
,
CE9F01C1261B3776009BA500
/* CoreDataUtils.swift in Sources */
,
CD67616D262587D30079D273
/* UITabBarController+Hide.swift in Sources */
,
CDC6126225E8DAB800188DA7
/* MoonPhaseCell.swift in Sources */
,
CD37D3D6260C93B3002669D6
/* MenuCellFactory.swift in Sources */
,
CD37D3FA260DF714002669D6
/* SettingsThemeCell.swift in Sources */
,
...
...
@@ -1336,6 +1382,7 @@
CD9B6B1125DBC723001D9B80
/* CubicCurveAlgorithm.swift in Sources */
,
CEC5270025E7BACB00DA58A5
/* WdtLocation.swift in Sources */
,
CE8962A726175DF500CA274A
/* _CoreLocation.swift in Sources */
,
CD67617026259D220079D273
/* RadarMapLayersController.swift in Sources */
,
CD866A65260F642600E96A5C
/* SettingsDetailsViewController.swift in Sources */
,
CD647D0225ED07D60034578B
/* TodayViewModel.swift in Sources */
,
CD593BD32608BC3F00C93428
/* ForecastDayCell.swift in Sources */
,
...
...
@@ -1355,6 +1402,7 @@
CD86246125E662BC0097F3FB
/* SunUvLineView.swift in Sources */
,
CD32CE0B260C744A00235081
/* MenuCoordinator.swift in Sources */
,
CD55E0BB2615EE2400CC4DC7
/* PollutantView.swift in Sources */
,
CD6761882625C3360079D273
/* RadarViewModel.swift in Sources */
,
CDF8F12A262089A200DB384A
/* MapTimeView.swift in Sources */
,
CEC526FA25E7959A00DA58A5
/* WeatherSource.swift in Sources */
,
CDF4808F261727E00076E9F5
/* CLAuthorizationStatus+Localized.swift in Sources */
,
...
...
1Weather.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
View file @
867a91f2
...
...
@@ -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
>
2
2
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
2
4
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
1.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
1Weather/Extensions/UITabBarController+Hide.swift
0 → 100644
View file @
867a91f2
//
// UITabBarController+Hide.swift
// 1Weather
//
// Created by Dmitry Stepanets on 13.04.2021.
//
import
UIKit
extension
UITabBarController
{
/**
Show or hide the tab bar.
- Parameter hidden: `true` if the bar should be hidden.
- Parameter animated: `true` if the action should be animated.
- Parameter transitionCoordinator: An optional `UIViewControllerTransitionCoordinator` to perform the animation
along side with. For example during a push on a `UINavigationController`.
*/
func
setTabBar
(
hidden
:
Bool
,
animated
:
Bool
=
true
,
along
transitionCoordinator
:
UIViewControllerTransitionCoordinator
?
=
nil
)
{
guard
isTabBarHidden
!=
hidden
else
{
return
}
let
offsetY
=
hidden
?
tabBar
.
frame
.
height
:
-
tabBar
.
frame
.
height
let
endFrame
=
tabBar
.
frame
.
offsetBy
(
dx
:
0
,
dy
:
offsetY
)
let
vc
:
UIViewController
?
=
viewControllers
?[
selectedIndex
]
var
newInsets
:
UIEdgeInsets
?
=
vc
?
.
additionalSafeAreaInsets
let
originalInsets
=
newInsets
newInsets
?
.
bottom
-=
offsetY
/// Helper method for updating child view controller's safe area insets.
func
set
(
childViewController
cvc
:
UIViewController
?,
additionalSafeArea
:
UIEdgeInsets
)
{
cvc
?
.
additionalSafeAreaInsets
=
additionalSafeArea
cvc
?
.
view
.
setNeedsLayout
()
}
// Update safe area insets for the current view controller before the animation takes place when hiding the bar.
if
hidden
,
let
insets
=
newInsets
{
set
(
childViewController
:
vc
,
additionalSafeArea
:
insets
)
}
guard
animated
else
{
tabBar
.
frame
=
endFrame
return
}
// Perform animation with coordinato if one is given. Update safe area insets _after_ the animation is complete,
// if we're showing the tab bar.
weak
var
tabBarRef
=
self
.
tabBar
if
let
tc
=
transitionCoordinator
{
tc
.
animateAlongsideTransition
(
in
:
self
.
view
,
animation
:
{
_
in
tabBarRef
?
.
frame
=
endFrame
})
{
context
in
if
!
hidden
,
let
insets
=
context
.
isCancelled
?
originalInsets
:
newInsets
{
set
(
childViewController
:
vc
,
additionalSafeArea
:
insets
)
}
}
}
else
{
UIView
.
animate
(
withDuration
:
0.25
,
animations
:
{
tabBarRef
?
.
frame
=
endFrame
})
{
didFinish
in
if
!
hidden
,
didFinish
,
let
insets
=
newInsets
{
set
(
childViewController
:
vc
,
additionalSafeArea
:
insets
)
}
}
}
}
/// `true` if the tab bar is currently hidden.
var
isTabBarHidden
:
Bool
{
return
!
tabBar
.
frame
.
intersects
(
view
.
frame
)
}
}
1Weather/Resources/Assets.xcassets/map_legend_close.imageset/Contents.json
0 → 100644
View file @
867a91f2
{
"images"
:
[
{
"filename"
:
"map_legend_close.pdf"
,
"idiom"
:
"universal"
}
],
"info"
:
{
"author"
:
"xcode"
,
"version"
:
1
},
"properties"
:
{
"preserves-vector-representation"
:
true
,
"template-rendering-intent"
:
"original"
}
}
1Weather/Resources/Assets.xcassets/map_legend_close.imageset/map_legend_close.pdf
0 → 100644
View file @
867a91f2
File added
1Weather/Resources/Assets.xcassets/radar_layer_pin.imageset/Contents.json
0 → 100644
View file @
867a91f2
{
"images"
:
[
{
"filename"
:
"radar_layer_pin.pdf"
,
"idiom"
:
"universal"
}
],
"info"
:
{
"author"
:
"xcode"
,
"version"
:
1
},
"properties"
:
{
"preserves-vector-representation"
:
true
,
"template-rendering-intent"
:
"template"
}
}
1Weather/Resources/Assets.xcassets/radar_layer_pin.imageset/radar_layer_pin.pdf
0 → 100644
View file @
867a91f2
File added
1Weather/Resources/en.lproj/Localizable.strings
View file @
867a91f2
...
...
@@ -118,6 +118,10 @@
"location.status.whenInUser" = "when in use";
"location.status.unknown" = "unknown";
//Radar
"radar.layers.base" = "Base layer";
"radar.layers.severe" = "Severe weather layer";
//Menu
"menu.goPremium" = "Go premium";
"menu.premium.desc" = "Experience app without ads @ $8.99 a year";
...
...
1Weather/UI/View controllers/Radar/Animators/MapLayersDismissAnimator.swift
0 → 100644
View file @
867a91f2
//
// MapLayersDismissAnimator.swift
// 1Weather
//
// Created by Dmitry Stepanets on 13.04.2021.
//
import
UIKit
class
MapLayersDismissAnimator
:
NSObject
,
UIViewControllerAnimatedTransitioning
{
func
transitionDuration
(
using
transitionContext
:
UIViewControllerContextTransitioning
?)
->
TimeInterval
{
return
0.25
}
func
animateTransition
(
using
transitionContext
:
UIViewControllerContextTransitioning
)
{
guard
let
fromViewController
=
transitionContext
.
viewController
(
forKey
:
.
from
)
else
{
return
}
let
container
=
transitionContext
.
containerView
UIView
.
animate
(
withDuration
:
transitionDuration
(
using
:
transitionContext
))
{
fromViewController
.
view
.
frame
.
origin
.
x
=
container
.
bounds
.
width
}
completion
:
{
finished
in
transitionContext
.
completeTransition
(
!
transitionContext
.
transitionWasCancelled
)
}
}
}
1Weather/UI/View controllers/Radar/Animators/MapLayersPresentationAnimator.swift
0 → 100644
View file @
867a91f2
//
// MapLayersPresentationAnimator.swift
// 1Weather
//
// Created by Dmitry Stepanets on 13.04.2021.
//
import
UIKit
class
MapLayersPresentationAnimator
:
NSObject
,
UIViewControllerAnimatedTransitioning
{
func
transitionDuration
(
using
transitionContext
:
UIViewControllerContextTransitioning
?)
->
TimeInterval
{
return
0.25
}
func
animateTransition
(
using
transitionContext
:
UIViewControllerContextTransitioning
)
{
guard
let
toViewController
=
transitionContext
.
viewController
(
forKey
:
.
to
)
else
{
return
}
let
container
=
transitionContext
.
containerView
toViewController
.
view
.
frame
=
.
init
(
x
:
container
.
bounds
.
width
,
y
:
0
,
width
:
220
,
height
:
container
.
frame
.
height
)
container
.
addSubview
(
toViewController
.
view
)
UIView
.
animate
(
withDuration
:
transitionDuration
(
using
:
transitionContext
))
{
toViewController
.
view
.
frame
.
origin
.
x
=
container
.
frame
.
width
-
220
}
completion
:
{
finished
in
transitionContext
.
completeTransition
(
finished
)
}
}
}
1Weather/UI/View controllers/Radar/Cells/RadarLayerCell.swift
0 → 100644
View file @
867a91f2
//
// RadarLayerCell.swift
// 1Weather
//
// Created by Dmitry Stepanets on 13.04.2021.
//
import
UIKit
class
RadarLayerCell
:
UITableViewCell
{
//Private
private
let
nameLabel
=
UILabel
()
private
let
pinButton
=
UIButton
()
override
init
(
style
:
UITableViewCell
.
CellStyle
,
reuseIdentifier
:
String
?)
{
super
.
init
(
style
:
style
,
reuseIdentifier
:
reuseIdentifier
)
prepareCell
()
preparePinButton
()
prepareNameLabel
()
updateUI
()
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
public
func
configure
(
text
:
String
)
{
nameLabel
.
text
=
text
}
override
func
traitCollectionDidChange
(
_
previousTraitCollection
:
UITraitCollection
?)
{
super
.
traitCollectionDidChange
(
previousTraitCollection
)
updateUI
()
}
private
func
updateUI
()
{
switch
interfaceStyle
{
case
.
light
:
nameLabel
.
textColor
=
ThemeManager
.
currentTheme
.
secondaryTextColor
case
.
dark
:
nameLabel
.
textColor
=
ThemeManager
.
currentTheme
.
primaryTextColor
}
}
@objc
private
func
handlePinButton
()
{
}
}
//MARK:- Prepare
private
extension
RadarLayerCell
{
func
prepareCell
()
{
selectionStyle
=
.
none
contentView
.
backgroundColor
=
ThemeManager
.
currentTheme
.
baseBackgroundColor
}
func
prepareNameLabel
()
{
nameLabel
.
lineBreakMode
=
.
byTruncatingTail
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
)
}
}
func
preparePinButton
()
{
pinButton
.
setImage
(
UIImage
(
named
:
"radar_layer_pin"
),
for
:
.
normal
)
pinButton
.
tintColor
=
.
white
pinButton
.
layer
.
cornerRadius
=
9
pinButton
.
backgroundColor
=
.
black
pinButton
.
addTarget
(
self
,
action
:
#selector(
handlePinButton
)
,
for
:
.
touchUpInside
)
contentView
.
addSubview
(
pinButton
)
pinButton
.
snp
.
makeConstraints
{
(
make
)
in
make
.
width
.
height
.
equalTo
(
18
)
make
.
centerY
.
equalToSuperview
()
make
.
right
.
equalToSuperview
()
.
inset
(
22
)
}
}
}
1Weather/UI/View controllers/Radar/Cells/RadarLayersCellFactory.swift
0 → 100644
View file @
867a91f2
//
// RadarLayersCellFactory.swift
// 1Weather
//
// Created by Dmitry Stepanets on 13.04.2021.
//
import
UIKit
private
enum
Section
{
case
base
case
severe
}
private
struct
LayerSection
{
let
type
:
Section
let
rows
:[
String
]
}
class
RadarLayersCellFactory
:
CellFactoryProtocol
{
//Private
private
let
sections
=
[
LayerSection
(
type
:
.
base
,
rows
:
[
"Temperature"
,
"Precipitation"
,
"Humidity"
,
"Clouds"
,
"Radar"
]),
LayerSection
(
type
:
.
severe
,
rows
:
[
"None"
,
"Fire"
,
"Floods"
])]
var
numberOfSections
:
Int
{
return
sections
.
count
}
func
numberOfRows
(
inSection
section
:
Int
)
->
Int
{
return
sections
[
section
]
.
rows
.
count
}
func
registerCells
(
on
tableView
:
UITableView
)
{
registerCell
(
type
:
RadarLayerCell
.
self
,
tableView
:
tableView
)
}
func
cellFromTableView
(
tableView
:
UITableView
,
indexPath
:
IndexPath
)
->
UITableViewCell
{
let
cell
=
dequeueReusableCell
(
type
:
RadarLayerCell
.
self
,
tableView
:
tableView
,
indexPath
:
indexPath
)
cell
.
configure
(
text
:
sections
[
indexPath
.
section
]
.
rows
[
indexPath
.
row
])
return
cell
}
}
1Weather/UI/View controllers/Radar/Controls/MapButton.swift
View file @
867a91f2
...
...
@@ -40,19 +40,18 @@ class MapButton: UIControl {
fatalError
(
"init(coder:) has not been implemented"
)
}
override
func
touchesBegan
(
_
touches
:
Set
<
UITouch
>
,
with
event
:
UIEvent
?)
{
super
.
touchesBegan
(
touches
,
with
:
event
)
UIView
.
performWithoutAnimation
{
self
.
alpha
=
0.7
}
}
override
func
touchesEnded
(
_
touches
:
Set
<
UITouch
>
,
with
event
:
UIEvent
?)
{
super
.
touchesBegan
(
touches
,
with
:
event
)
UIView
.
performWithoutAnimation
{
self
.
alpha
=
1
override
var
isHighlighted
:
Bool
{
didSet
{
if
isHighlighted
{
UIView
.
performWithoutAnimation
{
self
.
alpha
=
0.7
}
}
else
{
UIView
.
performWithoutAnimation
{
self
.
alpha
=
1
}
}
}
}
...
...
1Weather/UI/View controllers/Radar/Controls/MapLegendGradientView.swift
0 → 100644
View file @
867a91f2
//
// MapLegendGradientView.swift
// 1Weather
//
// Created by Dmitry Stepanets on 13.04.2021.
//
import
UIKit
class
MapLegendGradientView
:
UIView
{
private
let
colors
:[
UIColor
]
init
(
colors
:[
UIColor
])
{
self
.
colors
=
colors
super
.
init
(
frame
:
.
zero
)
prepare
()
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
override
class
var
layerClass
:
AnyClass
{
return
CAGradientLayer
.
self
}
}
//MARK:- Prepare
private
extension
MapLegendGradientView
{
func
prepare
()
{
self
.
clipsToBounds
=
true
self
.
backgroundColor
=
.
clear
guard
let
gradientLayer
=
self
.
layer
as?
CAGradientLayer
else
{
return
}
gradientLayer
.
colors
=
self
.
colors
.
map
{
$0
.
cgColor
}
gradientLayer
.
startPoint
=
.
init
(
x
:
0
,
y
:
0.5
)
gradientLayer
.
endPoint
=
.
init
(
x
:
1
,
y
:
0.5
)
}
}
1Weather/UI/View controllers/Radar/Controls/MapLegendView.swift
View file @
867a91f2
...
...
@@ -12,15 +12,15 @@ class MapLegendView: UIView {
//Private
private
let
kOpenWidth
:
CGFloat
=
180
private
let
kCloseWidth
:
CGFloat
=
40
private
let
kPrecipitationColors
=
[
UIColor
(
hex
:
0x9c57fa
)
.
cgColor
,
UIColor
(
hex
:
0x5ef0e8
)
.
withAlphaComponent
(
0.8
)
.
cgColor
,
UIColor
(
hex
:
0x4ebaf6
)
.
cgColor
]
private
static
let
kPrecipitationColors
=
[
UIColor
(
hex
:
0x9c57fa
)
,
UIColor
(
hex
:
0x5ef0e8
)
.
withAlphaComponent
(
0.8
),
UIColor
(
hex
:
0x4ebaf6
)]
private
let
button
=
UIButton
()
private
let
viewGradient
=
CAGradientLayer
()
private
let
buttonGradient
=
CAGradientLayer
()
private
let
legendGradient
=
CAGradientLayer
(
)
private
let
legendLabels
=
[
UILabel
]
()
private
var
widthConstraint
:
Constraint
?
private
let
legendGradient
=
MapLegendGradientView
(
colors
:
MapLegendView
.
kPrecipitationColors
)
private
let
legendLabels
StackView
=
UIStackView
()
private
var
legendLabels
=
[
UILabel
]()
private
var
isOpened
=
false
init
()
{
...
...
@@ -29,6 +29,7 @@ class MapLegendView: UIView {
prepareView
()
prepareViewGradient
()
prepareButton
()
prepareLegend
()
updateUI
()
}
...
...
@@ -75,8 +76,12 @@ class MapLegendView: UIView {
}
self
.
setNeedsLayout
()
self
.
button
.
setImage
(
isOpened
?
UIImage
(
named
:
"map_legend_close"
)
:
nil
,
for
:
.
normal
)
UIView
.
animate
(
withDuration
:
0.3
)
{
self
.
superview
?
.
layoutIfNeeded
()
self
.
legendGradient
.
alpha
=
self
.
isOpened
?
1
:
0
self
.
legendLabelsStackView
.
alpha
=
self
.
isOpened
?
1
:
0
self
.
layer
.
borderWidth
=
self
.
isOpened
?
0.5
:
0
}
}
}
...
...
@@ -85,14 +90,14 @@ class MapLegendView: UIView {
private
extension
MapLegendView
{
func
prepareView
()
{
self
.
clipsToBounds
=
false
self
.
layer
.
borderColor
=
UIColor
(
hex
:
0x353535
)
.
cgColor
layer
.
shadowColor
=
UIColor
.
black
.
withAlphaComponent
(
0.3
)
.
cgColor
layer
.
shadowOffset
=
.
init
(
width
:
0
,
height
:
3
)
layer
.
shadowOpacity
=
1
layer
.
shadowRadius
=
5
self
.
snp
.
makeConstraints
{
(
make
)
in
self
.
widthConstraint
=
make
.
width
.
equalTo
(
40
)
.
priority
(
1000
)
.
constraint
make
.
height
.
equalTo
(
40
)
.
priority
(
1000
)
make
.
width
.
height
.
equalTo
(
40
)
.
priority
(
1000
)
}
}
...
...
@@ -105,7 +110,7 @@ private extension MapLegendView {
}
func
prepareButton
()
{
buttonGradient
.
colors
=
self
.
kPrecipitationColors
buttonGradient
.
colors
=
MapLegendView
.
kPrecipitationColors
.
map
{
$0
.
cgColor
}
buttonGradient
.
startPoint
=
.
init
(
x
:
0
,
y
:
0.5
)
buttonGradient
.
endPoint
=
.
init
(
x
:
1
,
y
:
0.5
)
...
...
@@ -120,4 +125,37 @@ private extension MapLegendView {
make
.
centerY
.
equalToSuperview
()
}
}
func
prepareLegend
()
{
legendGradient
.
alpha
=
0
legendGradient
.
layer
.
cornerRadius
=
2
addSubview
(
legendGradient
)
legendGradient
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
equalTo
(
button
.
snp
.
right
)
.
offset
(
6
)
.
priority
(
999
)
make
.
top
.
equalToSuperview
()
.
inset
(
13
)
make
.
height
.
equalTo
(
4
)
make
.
right
.
equalToSuperview
()
.
inset
(
17
)
}
//Labels
legendLabelsStackView
.
alpha
=
0
legendLabelsStackView
.
axis
=
.
horizontal
legendLabelsStackView
.
distribution
=
.
equalCentering
addSubview
(
legendLabelsStackView
)
legendLabelsStackView
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
right
.
equalTo
(
legendGradient
)
make
.
top
.
equalTo
(
legendGradient
.
snp
.
bottom
)
.
offset
(
6
)
}
let
values
=
[
"1%"
,
"25%"
,
"50%"
,
"100%"
]
values
.
enumerated
()
.
forEach
{
let
label
=
UILabel
()
label
.
font
=
AppFont
.
SFPro
.
regular
(
size
:
10
)
label
.
text
=
$1
self
.
legendLabels
.
append
(
label
)
legendLabelsStackView
.
addArrangedSubview
(
label
)
}
}
}
1Weather/UI/View controllers/Radar/MapTimeControl/MapPinnedLayersView.swift
View file @
867a91f2
...
...
@@ -58,7 +58,7 @@ private extension MapPinnedLayersView {
pinContainer
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
equalToSuperview
()
make
.
height
.
equalTo
(
40
)
make
.
centerY
.
equalToSuperview
(
)
make
.
top
.
equalToSuperview
()
.
inset
(
3
)
make
.
width
.
equalTo
(
36
)
}
...
...
@@ -85,7 +85,7 @@ private extension MapPinnedLayersView {
scrollView
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
equalTo
(
pinContainer
.
snp
.
right
)
.
offset
(
6
)
make
.
right
.
equalToSuperview
()
make
.
top
.
bottom
.
equalToSuperview
()
.
inset
(
8
)
make
.
top
.
equalToSuperview
()
.
inset
(
8
)
}
}
...
...
1Weather/UI/View controllers/Radar/RadarMapLayersController.swift
0 → 100644
View file @
867a91f2
//
// RadarMapLayersController.swift
// 1Weather
//
// Created by Dmitry Stepanets on 13.04.2021.
//
import
UIKit
class
RadarMapLayersController
:
UIViewController
{
//Private
private
let
cellFactory
=
RadarLayersCellFactory
()
private
let
tableView
=
UITableView
(
frame
:
.
zero
,
style
:
.
grouped
)
init
()
{
super
.
init
(
nibName
:
nil
,
bundle
:
nil
)
modalPresentationStyle
=
.
custom
transitioningDelegate
=
self
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
view
.
backgroundColor
=
UIColor
.
black
.
withAlphaComponent
(
0.5
)
prepareTableView
()
}
override
func
viewDidLayoutSubviews
()
{
super
.
viewDidLayoutSubviews
()
self
.
tableView
.
layer
.
shadowPath
=
CGPath
(
rect
:
self
.
view
.
bounds
,
transform
:
nil
)
}
@objc
private
func
handleCloseButton
()
{
self
.
dismiss
(
animated
:
true
)
}
}
//MARK:- Prepare
private
extension
RadarMapLayersController
{
func
prepareController
()
{
}
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
tableView
.
delegate
=
self
tableView
.
rowHeight
=
46
tableView
.
tableFooterView
=
UIView
()
view
.
addSubview
(
tableView
)
tableView
.
snp
.
makeConstraints
{
(
make
)
in
make
.
edges
.
equalToSuperview
()
}
}
}
//MARK:- UITableView Data Source
extension
RadarMapLayersController
:
UITableViewDataSource
{
func
numberOfSections
(
in
tableView
:
UITableView
)
->
Int
{
return
cellFactory
.
numberOfSections
}
func
tableView
(
_
tableView
:
UITableView
,
numberOfRowsInSection
section
:
Int
)
->
Int
{
return
cellFactory
.
numberOfRows
(
inSection
:
section
)
}
func
tableView
(
_
tableView
:
UITableView
,
cellForRowAt
indexPath
:
IndexPath
)
->
UITableViewCell
{
return
cellFactory
.
cellFromTableView
(
tableView
:
tableView
,
indexPath
:
indexPath
)
}
}
//MARK:- UITableView Delegate
extension
RadarMapLayersController
:
UITableViewDelegate
{
func
tableView
(
_
tableView
:
UITableView
,
heightForHeaderInSection
section
:
Int
)
->
CGFloat
{
return
UITableView
.
automaticDimension
}
func
tableView
(
_
tableView
:
UITableView
,
heightForFooterInSection
section
:
Int
)
->
CGFloat
{
return
.
leastNormalMagnitude
}
func
tableView
(
_
tableView
:
UITableView
,
viewForFooterInSection
section
:
Int
)
->
UIView
?
{
return
nil
}
func
tableView
(
_
tableView
:
UITableView
,
viewForHeaderInSection
section
:
Int
)
->
UIView
?
{
let
container
=
UIView
()
container
.
backgroundColor
=
ThemeManager
.
currentTheme
.
baseBackgroundColor
switch
section
{
case
0
:
let
closeButton
=
UIButton
()
closeButton
.
setTitle
(
"general.close"
.
localized
()
.
capitalized
,
for
:
.
normal
)
closeButton
.
setTitleColor
(
ThemeManager
.
currentTheme
.
graphTintColor
,
for
:
.
normal
)
closeButton
.
addTarget
(
self
,
action
:
#selector(
handleCloseButton
)
,
for
:
.
touchUpInside
)
closeButton
.
titleLabel
?
.
font
=
AppFont
.
SFPro
.
regular
(
size
:
14
)
container
.
addSubview
(
closeButton
)
closeButton
.
snp
.
makeConstraints
{
(
make
)
in
make
.
height
.
equalTo
(
24
)
make
.
right
.
equalToSuperview
()
.
inset
(
20
)
make
.
top
.
equalToSuperview
()
.
inset
(
18
)
}
let
label
=
UILabel
()
label
.
textColor
=
view
.
interfaceStyle
==
.
light
?
ThemeManager
.
currentTheme
.
secondaryTextColor
:
ThemeManager
.
currentTheme
.
primaryTextColor
label
.
numberOfLines
=
0
label
.
lineBreakMode
=
.
byWordWrapping
label
.
font
=
AppFont
.
SFPro
.
bold
(
size
:
18
)
label
.
text
=
"radar.layers.base"
.
localized
()
container
.
addSubview
(
label
)
label
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
equalToSuperview
()
.
inset
(
18
)
make
.
top
.
bottom
.
equalToSuperview
()
.
inset
(
18
)
make
.
right
.
equalTo
(
closeButton
.
snp
.
left
)
.
offset
(
8
)
.
priority
(
999
)
}
case
1
:
let
label
=
UILabel
()
label
.
textColor
=
view
.
interfaceStyle
==
.
light
?
ThemeManager
.
currentTheme
.
secondaryTextColor
:
ThemeManager
.
currentTheme
.
primaryTextColor
label
.
numberOfLines
=
0
label
.
lineBreakMode
=
.
byWordWrapping
label
.
font
=
AppFont
.
SFPro
.
bold
(
size
:
18
)
label
.
text
=
"radar.layers.severe"
.
localized
()
container
.
addSubview
(
label
)
label
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
right
.
equalToSuperview
()
.
inset
(
18
)
make
.
top
.
bottom
.
equalToSuperview
()
.
inset
(
18
)
}
default
:
return
nil
}
return
container
}
}
//MARK:- Transitioning Delegate
extension
RadarMapLayersController
:
UIViewControllerTransitioningDelegate
{
func
animationController
(
forPresented
presented
:
UIViewController
,
presenting
:
UIViewController
,
source
:
UIViewController
)
->
UIViewControllerAnimatedTransitioning
?
{
return
MapLayersPresentationAnimator
()
}
func
animationController
(
forDismissed
dismissed
:
UIViewController
)
->
UIViewControllerAnimatedTransitioning
?
{
return
MapLayersDismissAnimator
()
}
}
1Weather/UI/View controllers/Radar/RadarViewController.swift
View file @
867a91f2
...
...
@@ -10,10 +10,13 @@ import MapKit
class
RadarViewController
:
UIViewController
{
//Private
private
let
kPinnedLayersHeight
:
CGFloat
=
43
private
let
radarViewModel
=
RadarViewModel
()
private
let
coordinator
:
RadarCoordinator
private
let
cityButton
=
NavigationCityButton
()
private
var
localizationObserver
:
Any
?
private
let
mapView
=
MKMapView
()
private
var
isFullScreen
=
false
//Buttons
private
let
fullScreenButton
=
MapButton
(
image
:
UIImage
(
named
:
"map_fullscreen"
))
...
...
@@ -23,7 +26,6 @@ class RadarViewController: UIViewController {
private
let
mapTimeControlView
=
MapTimeControlView
()
private
let
pinnedLayersView
=
MapPinnedLayersView
()
private
let
locationButton
=
UIButton
()
init
(
coordinator
:
RadarCoordinator
)
{
self
.
coordinator
=
coordinator
...
...
@@ -42,40 +44,73 @@ class RadarViewController: UIViewController {
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
radarViewModel
.
delegate
=
self
extendedLayoutIncludesOpaqueBars
=
true
edgesForExtendedLayout
=
[
.
bottom
]
prepareNavigationBar
()
prepareViewController
()
//
prepareMapView()
prepareMapView
()
prepareMapPinnedLayers
()
prepareLocationButton
()
prepareMapButtons
()
prepareMapTimeControl
()
updateUI
()
centerMap
()
cityButton
.
configure
(
with
:
radarViewModel
.
location
)
}
//Private
private
func
updateUI
()
{
view
.
backgroundColor
=
.
red
//
ThemeManager.currentTheme.baseBackgroundColor
view
.
backgroundColor
=
ThemeManager
.
currentTheme
.
baseBackgroundColor
locationButton
.
backgroundColor
=
ThemeManager
.
currentTheme
.
mapControlsColor
}
@objc
private
func
handleCityButton
()
{
private
func
centerMap
()
{
guard
let
coordinates
=
radarViewModel
.
location
?
.
coordinates
else
{
return
}
let
region
=
MKCoordinateRegion
(
center
:
coordinates
,
latitudinalMeters
:
4000
,
longitudinalMeters
:
4000
)
mapView
.
setRegion
(
region
,
animated
:
true
)
}
@objc
private
func
handle
Notification
Button
()
{
@objc
private
func
handle
City
Button
()
{
}
@objc
private
func
handle
FullScree
nButton
()
{
@objc
private
func
handle
Notificatio
nButton
()
{
}
@objc
private
func
handlePrecipitationButton
()
{
@objc
private
func
handleFullScreenButton
()
{
if
isFullScreen
{
self
.
navigationController
?
.
setNavigationBarHidden
(
false
,
animated
:
true
)
self
.
tabBarController
?
.
setTabBar
(
hidden
:
false
,
animated
:
true
)
self
.
pinnedLayersView
.
snp
.
updateConstraints
{
(
update
)
in
let
tabBarHeight
=
self
.
tabBarController
?
.
tabBar
.
frame
.
height
??
0
update
.
height
.
equalTo
(
kPinnedLayersHeight
+
tabBarHeight
)
}
isFullScreen
=
false
}
else
{
self
.
navigationController
?
.
setNavigationBarHidden
(
true
,
animated
:
true
)
self
.
tabBarController
?
.
setTabBar
(
hidden
:
true
,
animated
:
true
)
self
.
pinnedLayersView
.
snp
.
updateConstraints
{
(
update
)
in
update
.
height
.
equalTo
(
kPinnedLayersHeight
+
view
.
safeAreaInsets
.
bottom
)
}
isFullScreen
=
true
}
self
.
view
.
setNeedsLayout
()
UIView
.
animate
(
withDuration
:
0.25
)
{
self
.
view
.
layoutIfNeeded
()
}
}
@objc
private
func
handleLayersButton
()
{
let
layersViewController
=
RadarMapLayersController
()
self
.
present
(
layersViewController
,
animated
:
true
)
}
@objc
private
func
handleRadarButton
()
{
...
...
@@ -128,7 +163,8 @@ private extension RadarViewController {
pinnedLayersView
.
snp
.
makeConstraints
{
(
make
)
in
make
.
left
.
right
.
bottom
.
equalToSuperview
()
// make.height.equalTo(43)
let
tabBarHeight
=
self
.
tabBarController
?
.
tabBar
.
frame
.
height
??
0
make
.
height
.
equalTo
(
kPinnedLayersHeight
+
tabBarHeight
)
}
}
...
...
@@ -138,7 +174,7 @@ private extension RadarViewController {
view
.
addSubview
(
fullScreenButton
)
fullScreenButton
.
snp
.
makeConstraints
{
(
make
)
in
make
.
width
.
height
.
equalTo
(
40
)
make
.
top
.
equalTo
Superview
(
)
.
inset
(
16
)
make
.
top
.
equalTo
(
view
.
safeAreaLayoutGuide
.
snp
.
top
)
.
inset
(
16
)
make
.
right
.
equalToSuperview
()
.
inset
(
8
)
}
...
...
@@ -191,3 +227,11 @@ private extension RadarViewController {
}
}
}
//MARK:- ViewModel Delegate
extension
RadarViewController
:
ViewModelDelegate
{
func
viewModelDidChange
<
P
>
(
model
:
P
)
where
P
:
ViewModelProtocol
{
self
.
centerMap
()
cityButton
.
configure
(
with
:
radarViewModel
.
location
)
}
}
1Weather/ViewModels/RadarViewModel.swift
0 → 100644
View file @
867a91f2
//
// RadarViewModel.swift
// 1Weather
//
// Created by Dmitry Stepanets on 13.04.2021.
//
import
UIKit
class
RadarViewModel
:
ViewModelProtocol
{
//Public
public
weak
var
delegate
:
ViewModelDelegate
?
//Private
private
let
locationManager
=
LocationManager
.
shared
var
location
:
Location
?
{
return
locationManager
.
selectedLocation
}
init
()
{
locationManager
.
add
(
delegate
:
self
)
}
}
//MARK:- LocationManager Delegate
extension
RadarViewModel
:
LocationManagerDelegate
{
func
locationManager
(
_
locationManager
:
LocationManager
,
changedSelectedLocation
newLocation
:
Location
?)
{
DispatchQueue
.
main
.
async
{
self
.
delegate
?
.
viewModelDidChange
(
model
:
self
)
}
}
func
locationManager
(
_
locationManager
:
LocationManager
,
updatedLocationsList
newList
:
[
Location
])
{
// do nothing
}
}
1Weather/ViewModels/TodayViewModel.swift
View file @
867a91f2
...
...
@@ -10,6 +10,8 @@ import UIKit
class
TodayViewModel
:
ViewModelProtocol
{
//Public
public
weak
var
delegate
:
ViewModelDelegate
?
//Private
private
let
locationManager
=
LocationManager
.
shared
private(set)
var
location
:
Location
?
...
...
Pods/Pods.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
View file @
867a91f2
...
...
@@ -21,14 +21,14 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
0
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
1
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
Cirque.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
>
3
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
Cirque.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -40,7 +40,7 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
3
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
5
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
Firebase.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -52,7 +52,7 @@
<
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
>
6
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
FirebaseABTesting.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -64,7 +64,7 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
5
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
7
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
FirebaseAnalytics.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -76,7 +76,7 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
6
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
8
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
FirebaseCore.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -88,7 +88,7 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
7
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
9
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
FirebaseCoreDiagnostics.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -100,7 +100,7 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
8
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
10
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
FirebaseCrashlytics.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -112,7 +112,7 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
9
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
11
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
FirebaseInstallations.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -124,7 +124,7 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
1
0
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
1
2
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
FirebaseRemoteConfig.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -136,7 +136,7 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
1
1
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
1
3
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
Flurry-iOS-SDK.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -148,7 +148,7 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
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
4
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
GoogleAppMeasurement.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -160,7 +160,7 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
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
5
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
GoogleDataTransport.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -172,7 +172,7 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
1
4
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
1
6
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
GoogleUtilities.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -184,7 +184,7 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
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
>
Localize-Swift.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -196,7 +196,7 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
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
>
Logging.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -208,7 +208,7 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
18
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
20
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
MORichNotification.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -220,7 +220,7 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
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
9
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
MoEngage-iOS-SDK.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -232,14 +232,14 @@
<
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
>
2
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PromisesObjC.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
1
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
2
2
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
PromisesObjC.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -251,7 +251,7 @@
<
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
>
4
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
XMLCoder.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
...
...
@@ -270,7 +270,7 @@
<
k
e
y
>
isShown
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
19
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
21
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
k
e
y
>
nanopb.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
...
...
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