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
acc48b63
Commit
acc48b63
authored
Jul 01, 2021
by
Dmitriy Stepanets
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Finished WidgetPromotion controller UI and swipe down to close gesture
parent
6c9b7835
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
387 additions
and
64 deletions
+387
-64
1Weather-Icons.sketch
+0
-0
1Weather.xcodeproj/project.pbxproj
+12
-0
1Weather.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
+1
-1
1Weather/Info.plist
+2
-0
1Weather/Resources/Assets.xcassets/round_close.imageset/Contents.json
+15
-0
1Weather/Resources/Assets.xcassets/round_close.imageset/round_close.pdf
+0
-0
1Weather/Resources/OneWeatherColorsAsset.xcassets/widget_promotion_background.colorset/Contents.json
+38
-0
1Weather/Resources/OneWeatherColorsAsset.xcassets/widget_promotion_text.colorset/Contents.json
+38
-0
1Weather/Resources/en.lproj/Localizable.strings
+1
-0
1Weather/UI/Helpers/Themes/DefaultTheme.swift
+9
-0
1Weather/UI/Helpers/Themes/ThemeProtocol.swift
+28
-24
1Weather/UI/View controllers/Today/TodayViewController.swift
+5
-1
1Weather/UI/View controllers/WidgetPromotion/Animators/PromotionDismissAnimator.swift
+44
-0
1Weather/UI/View controllers/WidgetPromotion/Animators/PromotionPresentationAnimator.swift
+35
-0
1Weather/UI/View controllers/WidgetPromotion/Animators/WidgetPromotionInteractor.swift
+13
-0
1Weather/UI/View controllers/WidgetPromotion/Views/PromotionHeaderView.swift
+3
-10
1Weather/UI/View controllers/WidgetPromotion/Views/PromotionSmallWidgetView.swift
+22
-23
1Weather/UI/View controllers/WidgetPromotion/WidgetPromotionController.swift
+121
-5
No files found.
1Weather-Icons.sketch
View file @
acc48b63
No preview for this file type
1Weather.xcodeproj/project.pbxproj
View file @
acc48b63
...
@@ -57,6 +57,7 @@
...
@@ -57,6 +57,7 @@
CD3884842657BBCC0070FD6F
/* DelayedSaveStorage.framework in Embed Frameworks */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD3884822657BBCC0070FD6F
/* DelayedSaveStorage.framework */
;
settings
=
{
ATTRIBUTES
=
(
CodeSignOnCopy
,
RemoveHeadersOnCopy
,
);
};
};
CD3884842657BBCC0070FD6F
/* DelayedSaveStorage.framework in Embed Frameworks */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD3884822657BBCC0070FD6F
/* DelayedSaveStorage.framework */
;
settings
=
{
ATTRIBUTES
=
(
CodeSignOnCopy
,
RemoveHeadersOnCopy
,
);
};
};
CD39F2F225DE94C4009FE398
/* SunPhaseCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD39F2F125DE94C4009FE398
/* SunPhaseCell.swift */
;
};
CD39F2F225DE94C4009FE398
/* SunPhaseCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD39F2F125DE94C4009FE398
/* SunPhaseCell.swift */
;
};
CD39F2F525DE9571009FE398
/* ArrowButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD39F2F425DE9571009FE398
/* ArrowButton.swift */
;
};
CD39F2F525DE9571009FE398
/* ArrowButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD39F2F425DE9571009FE398
/* ArrowButton.swift */
;
};
CD3D567F268C705900DB99B6
/* PromotionPresentationAnimator.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD3D567E268C705900DB99B6
/* PromotionPresentationAnimator.swift */
;
};
CD3F6E6925FA59D4002DB99B
/* ForecastDetailPeriodButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD3F6E6825FA59D4002DB99B
/* ForecastDetailPeriodButton.swift */
;
};
CD3F6E6925FA59D4002DB99B
/* ForecastDetailPeriodButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD3F6E6825FA59D4002DB99B
/* ForecastDetailPeriodButton.swift */
;
};
CD3F6E6C25FA5A90002DB99B
/* PeriodButtonProtocol.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD3F6E6B25FA5A90002DB99B
/* PeriodButtonProtocol.swift */
;
};
CD3F6E6C25FA5A90002DB99B
/* PeriodButtonProtocol.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD3F6E6B25FA5A90002DB99B
/* PeriodButtonProtocol.swift */
;
};
CD4742D0261200500061AC95
/* TodayAlertCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD4742CF261200500061AC95
/* TodayAlertCell.swift */
;
};
CD4742D0261200500061AC95
/* TodayAlertCell.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
CD4742CF261200500061AC95
/* TodayAlertCell.swift */
;
};
...
@@ -305,6 +306,7 @@
...
@@ -305,6 +306,7 @@
CD3884822657BBCC0070FD6F
/* DelayedSaveStorage.framework */
=
{
isa
=
PBXFileReference
;
explicitFileType
=
wrapper.framework
;
path
=
DelayedSaveStorage.framework
;
sourceTree
=
BUILT_PRODUCTS_DIR
;
};
CD3884822657BBCC0070FD6F
/* DelayedSaveStorage.framework */
=
{
isa
=
PBXFileReference
;
explicitFileType
=
wrapper.framework
;
path
=
DelayedSaveStorage.framework
;
sourceTree
=
BUILT_PRODUCTS_DIR
;
};
CD39F2F125DE94C4009FE398
/* SunPhaseCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
SunPhaseCell.swift
;
sourceTree
=
"<group>"
;
};
CD39F2F125DE94C4009FE398
/* SunPhaseCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
SunPhaseCell.swift
;
sourceTree
=
"<group>"
;
};
CD39F2F425DE9571009FE398
/* ArrowButton.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ArrowButton.swift
;
sourceTree
=
"<group>"
;
};
CD39F2F425DE9571009FE398
/* ArrowButton.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ArrowButton.swift
;
sourceTree
=
"<group>"
;
};
CD3D567E268C705900DB99B6
/* PromotionPresentationAnimator.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
PromotionPresentationAnimator.swift
;
sourceTree
=
"<group>"
;
};
CD3F6E6825FA59D4002DB99B
/* ForecastDetailPeriodButton.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ForecastDetailPeriodButton.swift
;
sourceTree
=
"<group>"
;
};
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>"
;
};
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>"
;
};
CD4742CF261200500061AC95
/* TodayAlertCell.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TodayAlertCell.swift
;
sourceTree
=
"<group>"
;
};
...
@@ -666,6 +668,14 @@
...
@@ -666,6 +668,14 @@
path
=
Cells
;
path
=
Cells
;
sourceTree
=
"<group>"
;
sourceTree
=
"<group>"
;
};
};
CD3D567D268C703700DB99B6
/* Animators */
=
{
isa
=
PBXGroup
;
children
=
(
CD3D567E268C705900DB99B6
/* PromotionPresentationAnimator.swift */
,
);
path
=
Animators
;
sourceTree
=
"<group>"
;
};
CD5692B22653D46100A3CDBE
/* SplashAnimation */
=
{
CD5692B22653D46100A3CDBE
/* SplashAnimation */
=
{
isa
=
PBXGroup
;
isa
=
PBXGroup
;
children
=
(
children
=
(
...
@@ -815,6 +825,7 @@
...
@@ -815,6 +825,7 @@
CD857EA0268B290500B5E069
/* WidgetPromotion */
=
{
CD857EA0268B290500B5E069
/* WidgetPromotion */
=
{
isa
=
PBXGroup
;
isa
=
PBXGroup
;
children
=
(
children
=
(
CD3D567D268C703700DB99B6
/* Animators */
,
CD857EA3268B36D000B5E069
/* Views */
,
CD857EA3268B36D000B5E069
/* Views */
,
CD857EA1268B290500B5E069
/* WidgetPromotionController.swift */
,
CD857EA1268B290500B5E069
/* WidgetPromotionController.swift */
,
);
);
...
@@ -1537,6 +1548,7 @@
...
@@ -1537,6 +1548,7 @@
CD32CE0E260C770E00235081
/* MenuHeaderView.swift in Sources */
,
CD32CE0E260C770E00235081
/* MenuHeaderView.swift in Sources */
,
CD15DB3D25DA6C5100024727
/* ForecastTimePeriodControl.swift in Sources */
,
CD15DB3D25DA6C5100024727
/* ForecastTimePeriodControl.swift in Sources */
,
CD67617726259DD70079D273
/* MapLayersPresentationAnimator.swift in Sources */
,
CD67617726259DD70079D273
/* MapLayersPresentationAnimator.swift in Sources */
,
CD3D567F268C705900DB99B6
/* PromotionPresentationAnimator.swift in Sources */
,
CD7BF1582620410800A30DF5
/* RadarCoordinator.swift in Sources */
,
CD7BF1582620410800A30DF5
/* RadarCoordinator.swift in Sources */
,
CDD0F1EE25725BCF00CF5017
/* ThemeManager.swift in Sources */
,
CDD0F1EE25725BCF00CF5017
/* ThemeManager.swift in Sources */
,
CD1237F4255D889F00C98139
/* GradientView.swift in Sources */
,
CD1237F4255D889F00C98139
/* GradientView.swift in Sources */
,
...
...
1Weather.xcodeproj/xcuserdata/dstepanets.xcuserdatad/xcschemes/xcschememanagement.plist
View file @
acc48b63
...
@@ -12,7 +12,7 @@
...
@@ -12,7 +12,7 @@
<
k
e
y
>
OneWeatherNotificationServiceExtension.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
k
e
y
>
OneWeatherNotificationServiceExtension.xcscheme_
^#
shared
#^
_
<
/k
e
y
>
<
d
i
c
t
>
<
d
i
c
t
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
k
e
y
>
orderHint
<
/k
e
y
>
<
int
e
g
e
r
>
5
7
<
/int
e
g
e
r
>
<
int
e
g
e
r
>
5
8
<
/int
e
g
e
r
>
<
/
d
i
c
t
>
<
/
d
i
c
t
>
<
k
e
y
>
PG
(
Playground
)
1.xcscheme
<
/k
e
y
>
<
k
e
y
>
PG
(
Playground
)
1.xcscheme
<
/k
e
y
>
<
d
i
c
t
>
<
d
i
c
t
>
...
...
1Weather/Info.plist
View file @
acc48b63
...
@@ -420,6 +420,8 @@
...
@@ -420,6 +420,8 @@
<
string
>
UIInterfaceOrientationLandscapeLeft
<
/string
>
<
string
>
UIInterfaceOrientationLandscapeLeft
<
/string
>
<
string
>
UIInterfaceOrientationLandscapeRight
<
/string
>
<
string
>
UIInterfaceOrientationLandscapeRight
<
/string
>
<
/
a
rr
a
y
>
<
/
a
rr
a
y
>
<
k
e
y
>
GADNativeAdValidatorEnabled
<
/k
e
y
>
<
fa
ls
e
/
>
<
k
e
y
>
NSUserTrackingUsageDescription
<
/k
e
y
>
<
k
e
y
>
NSUserTrackingUsageDescription
<
/k
e
y
>
<
string
>
This
will
be
used
to
deliver
personalized
ads
to
you.
<
/string
>
<
string
>
This
will
be
used
to
deliver
personalized
ads
to
you.
<
/string
>
<
/
d
i
c
t
>
<
/
d
i
c
t
>
...
...
1Weather/Resources/Assets.xcassets/round_close.imageset/Contents.json
0 → 100644
View file @
acc48b63
{
"images"
:
[
{
"filename"
:
"round_close.pdf"
,
"idiom"
:
"universal"
}
],
"info"
:
{
"author"
:
"xcode"
,
"version"
:
1
},
"properties"
:
{
"preserves-vector-representation"
:
true
}
}
1Weather/Resources/Assets.xcassets/round_close.imageset/round_close.pdf
0 → 100644
View file @
acc48b63
File added
1Weather/Resources/OneWeatherColorsAsset.xcassets/widget_promotion_background.colorset/Contents.json
0 → 100644
View file @
acc48b63
{
"colors"
:
[
{
"color"
:
{
"color-space"
:
"srgb"
,
"components"
:
{
"alpha"
:
"1.000"
,
"blue"
:
"0x2B"
,
"green"
:
"0x26"
,
"red"
:
"0x26"
}
},
"idiom"
:
"universal"
},
{
"appearances"
:
[
{
"appearance"
:
"luminosity"
,
"value"
:
"dark"
}
],
"color"
:
{
"color-space"
:
"srgb"
,
"components"
:
{
"alpha"
:
"1.000"
,
"blue"
:
"0xFF"
,
"green"
:
"0xFF"
,
"red"
:
"0xFF"
}
},
"idiom"
:
"universal"
}
],
"info"
:
{
"author"
:
"xcode"
,
"version"
:
1
}
}
1Weather/Resources/OneWeatherColorsAsset.xcassets/widget_promotion_text.colorset/Contents.json
0 → 100644
View file @
acc48b63
{
"colors"
:
[
{
"color"
:
{
"color-space"
:
"srgb"
,
"components"
:
{
"alpha"
:
"1.000"
,
"blue"
:
"0xFF"
,
"green"
:
"0xFF"
,
"red"
:
"0xFF"
}
},
"idiom"
:
"universal"
},
{
"appearances"
:
[
{
"appearance"
:
"luminosity"
,
"value"
:
"dark"
}
],
"color"
:
{
"color-space"
:
"srgb"
,
"components"
:
{
"alpha"
:
"1.000"
,
"blue"
:
"0x2B"
,
"green"
:
"0x26"
,
"red"
:
"0x26"
}
},
"idiom"
:
"universal"
}
],
"info"
:
{
"author"
:
"xcode"
,
"version"
:
1
}
}
1Weather/Resources/en.lproj/Localizable.strings
View file @
acc48b63
...
@@ -282,3 +282,4 @@
...
@@ -282,3 +282,4 @@
"widget.promotion.small" = "Small";
"widget.promotion.small" = "Small";
"widget.promotion.medium" = "Medium";
"widget.promotion.medium" = "Medium";
"widget.promotion.large" = "Large";
"widget.promotion.large" = "Large";
"widget.promotion.learn" = "Learn to add widget";
1Weather/UI/Helpers/Themes/DefaultTheme.swift
View file @
acc48b63
...
@@ -120,4 +120,13 @@ struct DefaultTheme: ThemeProtocol {
...
@@ -120,4 +120,13 @@ struct DefaultTheme: ThemeProtocol {
var
nativeAdCallToActionColor
:
UIColor
{
var
nativeAdCallToActionColor
:
UIColor
{
return
UIColor
(
named
:
"native_ad_call_to_action_background"
)
??
.
red
return
UIColor
(
named
:
"native_ad_call_to_action_background"
)
??
.
red
}
}
//Widget promotion
var
widgetPromotionBackground
:
UIColor
{
return
UIColor
(
named
:
"widget_promotion_background"
)
??
.
red
}
var
widgetPromotionText
:
UIColor
{
return
UIColor
(
named
:
"widget_promotion_text"
)
??
.
red
}
}
}
1Weather/UI/Helpers/Themes/ThemeProtocol.swift
View file @
acc48b63
...
@@ -9,47 +9,51 @@ import UIKit
...
@@ -9,47 +9,51 @@ import UIKit
public
protocol
ThemeProtocol
{
public
protocol
ThemeProtocol
{
//Base
//Base
var
name
:
String
{
get
}
var
name
:
String
{
get
}
var
baseBackgroundColor
:
UIColor
{
get
}
var
baseBackgroundColor
:
UIColor
{
get
}
var
containerBackgroundColor
:
UIColor
{
get
}
var
containerBackgroundColor
:
UIColor
{
get
}
//Navigation bar
//Navigation bar
var
navigationBarBackgroundColor
:
UIColor
{
get
}
var
navigationBarBackgroundColor
:
UIColor
{
get
}
var
navigationTintColor
:
UIColor
{
get
}
var
navigationTintColor
:
UIColor
{
get
}
//Tab bar
//Tab bar
var
tabBarBackgroundColor
:
UIColor
{
get
}
var
tabBarBackgroundColor
:
UIColor
{
get
}
var
tabBarTintColor
:
UIColor
{
get
}
var
tabBarTintColor
:
UIColor
{
get
}
var
tabBarNormalColor
:
UIColor
{
get
}
var
tabBarNormalColor
:
UIColor
{
get
}
//Text
//Text
var
primaryTextColor
:
UIColor
{
get
}
var
primaryTextColor
:
UIColor
{
get
}
var
secondaryTextColor
:
UIColor
{
get
}
var
secondaryTextColor
:
UIColor
{
get
}
//Progress indicator
//Progress indicator
var
progressBackgroundColor
:
UIColor
{
get
}
var
progressBackgroundColor
:
UIColor
{
get
}
var
progressIndicatorColor
:
UIColor
{
get
}
var
progressIndicatorColor
:
UIColor
{
get
}
//Period button
//Period button
var
periodButtonBackgroundColor
:
UIColor
{
get
}
var
periodButtonBackgroundColor
:
UIColor
{
get
}
var
periodButtonSelectedBackgroundColor
:
UIColor
{
get
}
var
periodButtonSelectedBackgroundColor
:
UIColor
{
get
}
var
periodButtonBorderColor
:
UIColor
{
get
}
var
periodButtonBorderColor
:
UIColor
{
get
}
var
periodButtonShadowColor
:
UIColor
{
get
}
var
periodButtonShadowColor
:
UIColor
{
get
}
//Segment control
//Segment control
var
segmentTextColor
:
UIColor
{
get
}
var
segmentTextColor
:
UIColor
{
get
}
var
segmentSelectedTextColor
:
UIColor
{
get
}
var
segmentSelectedTextColor
:
UIColor
{
get
}
var
segmentBackgroundColor
:
UIColor
{
get
}
var
segmentBackgroundColor
:
UIColor
{
get
}
var
segmentBorderColor
:
UIColor
{
get
}
var
segmentBorderColor
:
UIColor
{
get
}
var
segmentSelectedGradient
:[
UIColor
]
{
get
}
var
segmentSelectedGradient
:
[
UIColor
]
{
get
}
//Graph
//Graph
var
graphColor
:
UIColor
{
get
}
var
graphColor
:
UIColor
{
get
}
var
graphTintColor
:
UIColor
{
get
}
var
graphTintColor
:
UIColor
{
get
}
//Map
//Map
var
mapControlsColor
:
UIColor
{
get
}
var
mapControlsColor
:
UIColor
{
get
}
//Ads
//Ads
var
nativeAdCallToActionColor
:
UIColor
{
get
}
var
nativeAdCallToActionColor
:
UIColor
{
get
}
//Widget promotion
var
widgetPromotionBackground
:
UIColor
{
get
}
var
widgetPromotionText
:
UIColor
{
get
}
}
}
1Weather/UI/View controllers/Today/TodayViewController.swift
View file @
acc48b63
...
@@ -65,7 +65,11 @@ class TodayViewController: UIViewController {
...
@@ -65,7 +65,11 @@ class TodayViewController: UIViewController {
}
}
@objc
private
func
handleNotificationButton
()
{
@objc
private
func
handleNotificationButton
()
{
self
.
coordinator
.
openNotificationsScreen
()
if
#available(iOS 14, *)
{
self
.
present
(
WidgetPromotionController
(),
animated
:
true
)
}
// self.coordinator.openNotificationsScreen()
}
}
}
}
...
...
1Weather/UI/View controllers/WidgetPromotion/Animators/PromotionDismissAnimator.swift
0 → 100644
View file @
acc48b63
//
// PromotionDismissAnimator.swift
// 1Weather
//
// Created by Dmitry Stepanets on 30.06.2021.
//
import
UIKit
class
PromotionDismissAnimator
:
NSObject
,
UIViewControllerAnimatedTransitioning
{
private
let
kDuration
=
0.25
func
transitionDuration
(
using
transitionContext
:
UIViewControllerContextTransitioning
?)
->
TimeInterval
{
return
kDuration
}
func
animateTransition
(
using
transitionContext
:
UIViewControllerContextTransitioning
)
{
guard
let
fromVC
=
transitionContext
.
viewController
(
forKey
:
.
from
),
let
toVC
=
transitionContext
.
viewController
(
forKey
:
.
to
)
else
{
return
}
// toVC is the Main View Controller
transitionContext
.
containerView
.
insertSubview
(
toVC
.
view
,
belowSubview
:
fromVC
.
view
)
// fromVC is the Modal VC.
// Hide it for now, since we're going to use snapshots instead.
fromVC
.
view
.
isHidden
=
true
// Create the snapshot.
if
let
snapshot
=
fromVC
.
view
.
snapshotView
(
afterScreenUpdates
:
false
)
{
// Don't forget to add it
transitionContext
.
containerView
.
insertSubview
(
snapshot
,
aboveSubview
:
toVC
.
view
)
UIView
.
animate
(
withDuration
:
kDuration
)
{
snapshot
.
center
.
y
+=
UIScreen
.
main
.
bounds
.
height
}
completion
:
{
_
in
transitionContext
.
completeTransition
(
!
transitionContext
.
transitionWasCancelled
)
}
}
}
}
1Weather/UI/View controllers/WidgetPromotion/Animators/PromotionPresentationAnimator.swift
0 → 100644
View file @
acc48b63
//
// PromotionPresentationAnimator.swift
// 1Weather
//
// Created by Dmitry Stepanets on 30.06.2021.
//
import
UIKit
@available(iOS 14, *)
class
PromotionPresentationAnimator
:
NSObject
,
UIViewControllerAnimatedTransitioning
{
func
transitionDuration
(
using
transitionContext
:
UIViewControllerContextTransitioning
?)
->
TimeInterval
{
return
0.25
}
func
animateTransition
(
using
transitionContext
:
UIViewControllerContextTransitioning
)
{
guard
let
toViewController
=
transitionContext
.
viewController
(
forKey
:
.
to
)
as?
WidgetPromotionController
else
{
return
}
let
container
=
transitionContext
.
containerView
let
contentHeight
=
toViewController
.
controllerContentHeight
toViewController
.
view
.
frame
=
.
init
(
x
:
0
,
y
:
container
.
bounds
.
height
,
width
:
container
.
frame
.
width
,
height
:
contentHeight
)
container
.
addSubview
(
toViewController
.
view
)
UIView
.
animate
(
withDuration
:
transitionDuration
(
using
:
transitionContext
))
{
toViewController
.
view
.
frame
.
origin
.
y
=
container
.
frame
.
height
-
contentHeight
}
completion
:
{
finished
in
transitionContext
.
completeTransition
(
finished
)
}
}
}
1Weather/UI/View controllers/WidgetPromotion/Animators/WidgetPromotionInteractor.swift
0 → 100644
View file @
acc48b63
//
// WidgetPromotionInteractor.swift
// 1Weather
//
// Created by Dmitry Stepanets on 30.06.2021.
//
import
UIKit
class
WidgetPromotionInteractor
:
UIPercentDrivenInteractiveTransition
{
var
hasStarted
=
false
var
shouldFinish
=
false
}
1Weather/UI/View controllers/WidgetPromotion/Views/PromotionHeaderView.swift
View file @
acc48b63
...
@@ -37,16 +37,9 @@ class PromotionHeaderView: UIView {
...
@@ -37,16 +37,9 @@ class PromotionHeaderView: UIView {
}
}
private
func
updateUI
()
{
private
func
updateUI
()
{
switch
interfaceStyle
{
plusImageView
.
tintColor
=
ThemeManager
.
currentTheme
.
widgetPromotionText
case
.
light
:
widgetLabel
.
textColor
=
ThemeManager
.
currentTheme
.
widgetPromotionText
plusImageView
.
tintColor
=
UIColor
(
hex
:
0x26262b
)
descriptionLabel
.
textColor
=
ThemeManager
.
currentTheme
.
widgetPromotionText
widgetLabel
.
textColor
=
UIColor
(
hex
:
0x26262b
)
descriptionLabel
.
textColor
=
UIColor
(
hex
:
0x26262b
)
case
.
dark
:
plusImageView
.
tintColor
=
.
white
widgetLabel
.
textColor
=
.
white
descriptionLabel
.
textColor
=
.
white
}
}
}
}
}
...
...
1Weather/UI/View controllers/WidgetPromotion/Views/PromotionSmallWidgetView.swift
View file @
acc48b63
...
@@ -21,9 +21,9 @@ class PromotionSmallWidgetView: UIView {
...
@@ -21,9 +21,9 @@ class PromotionSmallWidgetView: UIView {
preparePlaceholder
()
preparePlaceholder
()
prepareTopLabel
()
prepareTopLabel
()
prepareHorizontalLine
()
prepareHorizontalLine
()
prepareSizeNumberLabel
()
prepareVerticalLine
()
prepareSizesLabel
()
prepareSizesLabel
()
prepareVerticalLine
()
prepareSizeNumberLabel
()
updateUI
()
updateUI
()
}
}
...
@@ -37,19 +37,17 @@ class PromotionSmallWidgetView: UIView {
...
@@ -37,19 +37,17 @@ class PromotionSmallWidgetView: UIView {
}
}
private
func
updateUI
()
{
private
func
updateUI
()
{
topLabel
.
textColor
=
ThemeManager
.
currentTheme
.
widgetPromotionText
sizeNumberLabel
.
textColor
=
ThemeManager
.
currentTheme
.
widgetPromotionText
sizesLabel
.
textColor
=
ThemeManager
.
currentTheme
.
widgetPromotionText
switch
interfaceStyle
{
switch
interfaceStyle
{
case
.
light
:
case
.
light
:
topLabel
.
textColor
=
UIColor
(
hex
:
0x26262b
)
sizeNumberLabel
.
textColor
=
UIColor
(
hex
:
0x26262b
)
sizesLabel
.
textColor
=
UIColor
(
hex
:
0x26262b
)
horizontalLineView
.
backgroundColor
=
UIColor
.
black
.
withAlphaComponent
(
0.1
)
verticalLineView
.
backgroundColor
=
UIColor
.
black
.
withAlphaComponent
(
0.1
)
case
.
dark
:
topLabel
.
textColor
=
.
white
sizeNumberLabel
.
textColor
=
.
white
sizesLabel
.
textColor
=
.
white
horizontalLineView
.
backgroundColor
=
UIColor
(
hex
:
0xffffff
)
.
withAlphaComponent
(
0.1
)
horizontalLineView
.
backgroundColor
=
UIColor
(
hex
:
0xffffff
)
.
withAlphaComponent
(
0.1
)
verticalLineView
.
backgroundColor
=
UIColor
(
hex
:
0xffffff
)
.
withAlphaComponent
(
0.1
)
verticalLineView
.
backgroundColor
=
UIColor
(
hex
:
0xffffff
)
.
withAlphaComponent
(
0.1
)
case
.
dark
:
horizontalLineView
.
backgroundColor
=
UIColor
.
black
.
withAlphaComponent
(
0.1
)
verticalLineView
.
backgroundColor
=
UIColor
.
black
.
withAlphaComponent
(
0.1
)
}
}
}
}
}
}
...
@@ -111,7 +109,7 @@ private extension PromotionSmallWidgetView {
...
@@ -111,7 +109,7 @@ private extension PromotionSmallWidgetView {
addSubview
(
sizeNumberLabel
)
addSubview
(
sizeNumberLabel
)
sizeNumberLabel
.
snp
.
makeConstraints
{
make
in
sizeNumberLabel
.
snp
.
makeConstraints
{
make
in
make
.
left
.
equalTo
(
widgetPlaceholder
.
snp
.
right
)
.
offset
(
33
)
make
.
right
.
equalTo
(
verticalLineView
.
snp
.
left
)
.
offset
(
-
20
)
make
.
top
.
equalTo
(
horizontalLineView
.
snp
.
bottom
)
.
offset
(
17
)
make
.
top
.
equalTo
(
horizontalLineView
.
snp
.
bottom
)
.
offset
(
17
)
}
}
}
}
...
@@ -123,8 +121,8 @@ private extension PromotionSmallWidgetView {
...
@@ -123,8 +121,8 @@ private extension PromotionSmallWidgetView {
verticalLineView
.
snp
.
makeConstraints
{
make
in
verticalLineView
.
snp
.
makeConstraints
{
make
in
make
.
width
.
equalTo
(
1
)
make
.
width
.
equalTo
(
1
)
make
.
top
.
equalTo
(
horizontalLineView
.
snp
.
bottom
)
.
offset
(
10
)
make
.
top
.
equalTo
(
horizontalLineView
.
snp
.
bottom
)
.
offset
(
10
)
make
.
height
.
equalTo
(
70
)
make
.
height
.
equalTo
(
sizesLabel
)
make
.
centerX
.
equalTo
(
horizontalLineView
)
make
.
right
.
equalTo
(
sizesLabel
.
snp
.
left
)
.
offset
(
-
13
)
}
}
}
}
...
@@ -133,13 +131,15 @@ private extension PromotionSmallWidgetView {
...
@@ -133,13 +131,15 @@ private extension PromotionSmallWidgetView {
let
medium
=
"widget.promotion.medium"
.
localized
()
let
medium
=
"widget.promotion.medium"
.
localized
()
let
large
=
"widget.promotion.large"
.
localized
()
let
large
=
"widget.promotion.large"
.
localized
()
let
paragraph
=
NSMutableParagraphStyle
()
paragraph
.
lineSpacing
=
4
let
attrString
=
NSMutableAttributedString
(
string
:
small
+
"
\n
"
+
medium
+
"
\n
"
+
large
)
let
attrString
=
NSMutableAttributedString
(
string
:
small
+
"
\n
"
+
medium
+
"
\n
"
+
large
)
attrString
.
addAttribute
(
.
font
,
attrString
.
addAttributes
([
.
font
:
UIFont
.
systemFont
(
ofSize
:
14
,
weight
:
.
medium
),
value
:
UIFont
.
systemFont
(
ofSize
:
14
,
weight
:
.
medium
),
.
paragraphStyle
:
paragraph
],
range
:
.
init
(
location
:
0
,
length
:
small
.
count
))
range
:
.
init
(
location
:
0
,
length
:
small
.
count
))
attrString
.
addAttribute
(
.
font
,
attrString
.
addAttributes
([
.
font
:
UIFont
.
systemFont
(
ofSize
:
20
,
weight
:
.
semibold
)],
value
:
UIFont
.
systemFont
(
ofSize
:
20
,
weight
:
.
semibold
),
range
:
.
init
(
location
:
small
.
count
,
length
:
medium
.
count
+
1
))
range
:
.
init
(
location
:
small
.
count
,
length
:
medium
.
count
+
1
))
attrString
.
addAttribute
(
.
font
,
attrString
.
addAttribute
(
.
font
,
value
:
UIFont
.
systemFont
(
ofSize
:
28
,
weight
:
.
bold
),
value
:
UIFont
.
systemFont
(
ofSize
:
28
,
weight
:
.
bold
),
range
:
.
init
(
location
:
small
.
count
+
medium
.
count
+
1
,
length
:
large
.
count
+
1
))
range
:
.
init
(
location
:
small
.
count
+
medium
.
count
+
1
,
length
:
large
.
count
+
1
))
...
@@ -151,9 +151,8 @@ private extension PromotionSmallWidgetView {
...
@@ -151,9 +151,8 @@ private extension PromotionSmallWidgetView {
addSubview
(
sizesLabel
)
addSubview
(
sizesLabel
)
sizesLabel
.
snp
.
makeConstraints
{
make
in
sizesLabel
.
snp
.
makeConstraints
{
make
in
make
.
left
.
equalTo
(
verticalLineView
.
snp
.
right
)
.
offset
(
13
)
make
.
top
.
equalTo
(
horizontalLineView
.
snp
.
bottom
)
.
offset
(
8
)
make
.
top
.
equalTo
(
verticalLineView
)
make
.
right
.
equalTo
(
horizontalLineView
)
make
.
right
.
equalToSuperview
()
}
}
}
}
}
}
1Weather/UI/View controllers/WidgetPromotion/WidgetPromotionController.swift
View file @
acc48b63
...
@@ -10,17 +10,45 @@ import UIKit
...
@@ -10,17 +10,45 @@ import UIKit
@available(iOS 14, *)
@available(iOS 14, *)
class
WidgetPromotionController
:
UIViewController
{
class
WidgetPromotionController
:
UIViewController
{
//Private
//Private
private
let
kPanTopInset
:
CGFloat
=
10
private
let
kScrollViewTopInset
:
CGFloat
=
36
private
let
controllerPanView
=
UIView
()
private
let
controllerPanView
=
UIView
()
private
let
closeButton
=
UIButton
()
private
let
closeButton
=
UIButton
()
private
let
scrollView
=
UIScrollView
()
private
let
scrollView
=
UIScrollView
()
private
let
stackView
=
UIStackView
()
private
let
stackView
=
UIStackView
()
private
let
footerView
=
UIView
()
private
let
learnButton
=
UIButton
()
private
var
initialTouchPoint
=
CGPoint
(
x
:
0
,
y
:
0
)
private
lazy
var
panGesture
:
UIPanGestureRecognizer
=
{
let
gesture
=
UIPanGestureRecognizer
(
target
:
self
,
action
:
#selector(
handlePanGesture(sender:)
)
)
return
gesture
}()
//Public
var
controllerContentHeight
:
CGFloat
{
let
scrollViewBottomInset
:
CGFloat
=
4
let
pan
=
controllerPanView
.
frame
.
height
+
kPanTopInset
let
stackHeight
=
stackView
.
frame
.
height
let
footerHeight
=
footerView
.
frame
.
height
let
safeAreaInset
=
UIApplication
.
shared
.
keyWindow
?
.
safeAreaInsets
.
bottom
??
0
return
pan
+
kScrollViewTopInset
+
stackHeight
+
scrollViewBottomInset
+
footerHeight
+
safeAreaInset
}
init
()
{
init
()
{
super
.
init
(
nibName
:
nil
,
bundle
:
nil
)
super
.
init
(
nibName
:
nil
,
bundle
:
nil
)
modalPresentationStyle
=
.
custom
transitioningDelegate
=
self
}
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
prepareView
()
prepareView
()
preparePanView
()
preparePanView
()
prepareCloseButton
()
prepareCloseButton
()
prepareFooterView
()
prepareScrollView
()
prepareScrollView
()
prepareStackView
()
prepareStackView
()
updateUI
()
updateUI
()
...
@@ -34,8 +62,45 @@ class WidgetPromotionController: UIViewController {
...
@@ -34,8 +62,45 @@ class WidgetPromotionController: UIViewController {
self
.
dismiss
(
animated
:
true
)
self
.
dismiss
(
animated
:
true
)
}
}
@objc
private
func
handleLearnButton
()
{
}
@objc
private
func
handlePanGesture
(
sender
:
UIPanGestureRecognizer
)
{
let
touchPoint
=
sender
.
location
(
in
:
self
.
view
?
.
window
)
let
originalOffsetY
=
UIScreen
.
main
.
bounds
.
height
-
self
.
view
.
bounds
.
height
switch
sender
.
state
{
case
.
began
:
initialTouchPoint
=
touchPoint
case
.
changed
:
if
touchPoint
.
y
-
initialTouchPoint
.
y
>
0
{
view
.
frame
.
origin
.
y
=
originalOffsetY
+
(
touchPoint
.
y
-
initialTouchPoint
.
y
)
}
case
.
cancelled
,
.
ended
:
if
touchPoint
.
y
-
initialTouchPoint
.
y
>
80
{
self
.
dismiss
(
animated
:
true
,
completion
:
nil
)
}
else
{
UIView
.
animate
(
withDuration
:
0.25
,
animations
:
{
self
.
view
.
frame
.
origin
.
y
=
originalOffsetY
})
}
break
default
:
break
}
}
private
func
updateUI
()
{
private
func
updateUI
()
{
view
.
backgroundColor
=
ThemeManager
.
currentTheme
.
baseBackgroundColor
view
.
backgroundColor
=
ThemeManager
.
currentTheme
.
widgetPromotionBackground
footerView
.
backgroundColor
=
ThemeManager
.
currentTheme
.
widgetPromotionBackground
switch
view
.
interfaceStyle
{
case
.
light
:
footerView
.
layer
.
shadowColor
=
UIColor
(
hex
:
0x4c4c4c
)
.
cgColor
case
.
dark
:
footerView
.
layer
.
shadowColor
=
UIColor
(
hex
:
0xAAAAAA
)
.
cgColor
}
}
}
}
}
...
@@ -43,9 +108,16 @@ class WidgetPromotionController: UIViewController {
...
@@ -43,9 +108,16 @@ class WidgetPromotionController: UIViewController {
@available(iOS 14, *)
@available(iOS 14, *)
private
extension
WidgetPromotionController
{
private
extension
WidgetPromotionController
{
func
prepareView
()
{
func
prepareView
()
{
view
.
addGestureRecognizer
(
panGesture
)
view
.
clipsToBounds
=
true
view
.
clipsToBounds
=
true
view
.
layer
.
cornerRadius
=
24
view
.
layer
.
cornerRadius
=
24
view
.
layer
.
maskedCorners
=
[
.
layerMinXMinYCorner
,
.
layerMaxXMinYCorner
]
view
.
layer
.
maskedCorners
=
[
.
layerMinXMinYCorner
,
.
layerMaxXMinYCorner
]
view
.
layer
.
shadowColor
=
UIColor
.
black
.
cgColor
view
.
layer
.
shadowOpacity
=
0.5
view
.
layer
.
shadowOffset
=
.
init
(
width
:
0
,
height
:
0
)
view
.
layer
.
shadowRadius
=
18
}
}
func
preparePanView
()
{
func
preparePanView
()
{
...
@@ -56,14 +128,14 @@ private extension WidgetPromotionController {
...
@@ -56,14 +128,14 @@ private extension WidgetPromotionController {
controllerPanView
.
snp
.
makeConstraints
{
make
in
controllerPanView
.
snp
.
makeConstraints
{
make
in
make
.
width
.
equalTo
(
30
)
make
.
width
.
equalTo
(
30
)
make
.
height
.
equalTo
(
4
)
make
.
height
.
equalTo
(
4
)
make
.
top
.
equalToSuperview
()
.
inset
(
10
)
make
.
top
.
equalToSuperview
()
.
inset
(
kPanTopInset
)
make
.
centerX
.
equalToSuperview
()
make
.
centerX
.
equalToSuperview
()
}
}
}
}
func
prepareCloseButton
()
{
func
prepareCloseButton
()
{
closeButton
.
addTarget
(
self
,
action
:
#selector(
handleCloseButton
)
,
for
:
.
touchUpInside
)
closeButton
.
addTarget
(
self
,
action
:
#selector(
handleCloseButton
)
,
for
:
.
touchUpInside
)
closeButton
.
setImage
(
UIImage
(
systemName
:
"xmark.circle.fill
"
),
for
:
.
normal
)
closeButton
.
setImage
(
UIImage
(
named
:
"round_close
"
),
for
:
.
normal
)
closeButton
.
imageView
?
.
contentMode
=
.
scaleAspectFit
closeButton
.
imageView
?
.
contentMode
=
.
scaleAspectFit
closeButton
.
tintColor
=
UIColor
(
hex
:
0xe4e4e4
)
.
withAlphaComponent
(
0.4
)
closeButton
.
tintColor
=
UIColor
(
hex
:
0xe4e4e4
)
.
withAlphaComponent
(
0.4
)
view
.
addSubview
(
closeButton
)
view
.
addSubview
(
closeButton
)
...
@@ -78,8 +150,9 @@ private extension WidgetPromotionController {
...
@@ -78,8 +150,9 @@ private extension WidgetPromotionController {
func
prepareScrollView
()
{
func
prepareScrollView
()
{
view
.
addSubview
(
scrollView
)
view
.
addSubview
(
scrollView
)
scrollView
.
snp
.
makeConstraints
{
make
in
scrollView
.
snp
.
makeConstraints
{
make
in
make
.
left
.
bottom
.
right
.
equalToSuperview
()
make
.
left
.
right
.
equalToSuperview
()
make
.
top
.
equalToSuperview
()
.
inset
(
36
)
make
.
top
.
equalToSuperview
()
.
inset
(
kScrollViewTopInset
)
make
.
bottom
.
equalTo
(
footerView
.
snp
.
top
)
.
offset
(
4
)
}
}
}
}
...
@@ -94,5 +167,48 @@ private extension WidgetPromotionController {
...
@@ -94,5 +167,48 @@ private extension WidgetPromotionController {
stackView
.
snp
.
makeConstraints
{
make
in
stackView
.
snp
.
makeConstraints
{
make
in
make
.
edges
.
width
.
equalToSuperview
()
make
.
edges
.
width
.
equalToSuperview
()
}
}
stackView
.
layoutIfNeeded
()
}
func
prepareFooterView
()
{
footerView
.
layer
.
shadowOpacity
=
0.5
footerView
.
layer
.
shadowRadius
=
7
footerView
.
layer
.
shadowOffset
=
.
init
(
width
:
0
,
height
:
0
)
view
.
addSubview
(
footerView
)
learnButton
.
addTarget
(
self
,
action
:
#selector(
handleLearnButton
)
,
for
:
.
touchUpInside
)
learnButton
.
setTitle
(
"widget.promotion.learn"
.
localized
(),
for
:
.
normal
)
learnButton
.
setTitleColor
(
ThemeManager
.
currentTheme
.
graphTintColor
,
for
:
.
normal
)
learnButton
.
setTitleColor
(
ThemeManager
.
currentTheme
.
graphTintColor
.
darken
(
by
:
10
),
for
:
.
highlighted
)
learnButton
.
layer
.
borderWidth
=
2
learnButton
.
layer
.
borderColor
=
ThemeManager
.
currentTheme
.
graphTintColor
.
cgColor
learnButton
.
layer
.
cornerRadius
=
6
footerView
.
addSubview
(
learnButton
)
//Constraints
footerView
.
snp
.
makeConstraints
{
make
in
make
.
left
.
right
.
bottom
.
equalToSuperview
()
}
learnButton
.
snp
.
makeConstraints
{
make
in
make
.
left
.
right
.
equalToSuperview
()
.
inset
(
20
)
make
.
top
.
equalToSuperview
()
.
inset
(
10
)
let
safeAreaInset
=
UIApplication
.
shared
.
keyWindow
?
.
safeAreaInsets
.
bottom
??
0
make
.
bottom
.
equalToSuperview
()
.
inset
(
safeAreaInset
+
10
)
}
footerView
.
layoutIfNeeded
()
}
}
//MARK:- Transitioning Delegate
@available(iOS 14, *)
extension
WidgetPromotionController
:
UIViewControllerTransitioningDelegate
{
func
animationController
(
forPresented
presented
:
UIViewController
,
presenting
:
UIViewController
,
source
:
UIViewController
)
->
UIViewControllerAnimatedTransitioning
?
{
return
PromotionPresentationAnimator
()
}
func
animationController
(
forDismissed
dismissed
:
UIViewController
)
->
UIViewControllerAnimatedTransitioning
?
{
return
nil
}
}
}
}
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