//
// C o p y r i g h t ( c ) 2 0 1 8 O p e n W h i s p e r S y s t e m s . A l l r i g h t s r e s e r v e d .
//
import Foundation
import SignalMessaging
private class IntroducingCustomNotificationAudioExperienceUpgradeViewController : ExperienceUpgradeViewController {
var buttonAction : ( ( UIButton ) -> Void ) ?
override func loadView ( ) {
self . view = UIView . container ( )
// / C r e a t e V i e w s
// T i t l e l a b e l
let titleLabel = UILabel ( )
view . addSubview ( titleLabel )
titleLabel . text = header
titleLabel . textAlignment = . center
titleLabel . font = UIFont . ows_regularFont ( withSize : ScaleFromIPhone5 ( 24 ) )
titleLabel . textColor = UIColor . white
titleLabel . minimumScaleFactor = 0.5
titleLabel . adjustsFontSizeToFitWidth = true
// B o d y l a b e l
let bodyLabel = UILabel ( )
self . bodyLabel = bodyLabel
view . addSubview ( bodyLabel )
bodyLabel . text = body
bodyLabel . font = UIFont . ows_lightFont ( withSize : ScaleFromIPhone5To7Plus ( 17 , 22 ) )
bodyLabel . textColor = UIColor . black
bodyLabel . numberOfLines = 0
bodyLabel . lineBreakMode = . byWordWrapping
bodyLabel . textAlignment = . center
// I m a g e
let imageView = UIImageView ( image : image )
view . addSubview ( imageView )
imageView . contentMode = . scaleAspectFit
let buttonTitle = NSLocalizedString ( " UPGRADE_EXPERIENCE_INTRODUCING_NOTIFICATION_AUDIO_SETTINGS_BUTTON " , comment : " button label shown one time, after upgrade " )
let button = addButton ( title : buttonTitle ) { _ in
// d i s m i s s t h e m o d a l l y p r e s e n t e d v i e w c o n t r o l l e r , t h e n p r o c e e d .
self . experienceUpgradesPageViewController . dismiss ( animated : true ) {
guard let fromViewController = UIApplication . shared . frontmostViewController as ? HomeViewController else {
owsFail ( " unexpected frontmostViewController: \( String ( describing : UIApplication . shared . frontmostViewController ) ) " )
return
}
// C o n s t r u c t t h e " s e t t i n g s " v i e w & p u s h t h e " n o t i f i c a t i o n s s e t t i n g s " v i e w .
let navigationController = AppSettingsViewController . inModalNavigationController ( )
navigationController . pushViewController ( NotificationSettingsViewController ( ) , animated : false )
fromViewController . present ( navigationController , animated : true )
}
}
let bottomSpacer = UIView ( )
view . addSubview ( bottomSpacer )
// / L a y o u t V i e w s
// I m a g e l a y o u t
imageView . autoAlignAxis ( toSuperviewAxis : . vertical )
imageView . autoPinToSquareAspectRatio ( )
imageView . autoPinEdge ( . top , to : . bottom , of : titleLabel , withOffset : ScaleFromIPhone5To7Plus ( 36 , 40 ) )
imageView . autoSetDimension ( . height , toSize : ScaleFromIPhone5 ( 225 ) )
// T i t l e l a b e l l a y o u t
titleLabel . autoSetDimension ( . height , toSize : ScaleFromIPhone5 ( 40 ) )
titleLabel . autoPinWidthToSuperview ( withMargin : ScaleFromIPhone5To7Plus ( 16 , 24 ) )
titleLabel . autoPinTopToSuperview ( )
// B o d y l a b e l l a y o u t
bodyLabel . autoPinEdge ( . top , to : . bottom , of : imageView , withOffset : ScaleFromIPhone5To7Plus ( 18 , 28 ) )
bodyLabel . autoPinWidthToSuperview ( withMargin : bodyMargin )
bodyLabel . setContentHuggingVerticalHigh ( )
// B u t t o n l a y o u t
button . autoPinEdge ( . top , to : . bottom , of : bodyLabel , withOffset : ScaleFromIPhone5 ( 16 ) )
button . autoPinWidthToSuperview ( withMargin : ScaleFromIPhone5 ( 32 ) )
bottomSpacer . autoPinEdge ( . top , to : . bottom , of : button , withOffset : ScaleFromIPhone5 ( 16 ) )
bottomSpacer . autoPinEdge ( toSuperviewEdge : . bottom )
bottomSpacer . autoPinWidthToSuperview ( )
}
// MARK: - A c t i o n s
func addButton ( title : String , action : @ escaping ( UIButton ) -> Void ) -> UIButton {
self . buttonAction = action
let button = MultiLineButton ( )
view . addSubview ( button )
button . setTitle ( title , for : . normal )
button . setTitleColor ( UIColor . ows_signalBrandBlue , for : . normal )
button . isUserInteractionEnabled = true
button . addTarget ( self , action : #selector ( didTapButton ) , for : . touchUpInside )
button . contentEdgeInsets = UIEdgeInsets ( top : 10 , left : 10 , bottom : 10 , right : 10 )
button . titleLabel ? . textAlignment = . center
button . titleLabel ? . font = UIFont . ows_mediumFont ( withSize : ScaleFromIPhone5 ( 18 ) )
return button
}
func didTapButton ( sender : UIButton ) {
Logger . debug ( " \( TAG ) in \( #function ) " )
guard let buttonAction = self . buttonAction else {
owsFail ( " \( TAG ) button action was nil " )
return
}
buttonAction ( sender )
}
}
private class IntroductingReadReceiptsExperienceUpgradeViewController : ExperienceUpgradeViewController {
var buttonAction : ( ( UIButton ) -> Void ) ?
override func loadView ( ) {
self . view = UIView . container ( )
// / C r e a t e V i e w s
// T i t l e l a b e l
let titleLabel = UILabel ( )
view . addSubview ( titleLabel )
titleLabel . text = header
titleLabel . textAlignment = . center
titleLabel . font = UIFont . ows_regularFont ( withSize : ScaleFromIPhone5 ( 24 ) )
titleLabel . textColor = UIColor . white
titleLabel . minimumScaleFactor = 0.5
titleLabel . adjustsFontSizeToFitWidth = true
// B o d y l a b e l
let bodyLabel = UILabel ( )
self . bodyLabel = bodyLabel
view . addSubview ( bodyLabel )
bodyLabel . text = body
bodyLabel . font = UIFont . ows_lightFont ( withSize : ScaleFromIPhone5To7Plus ( 17 , 22 ) )
bodyLabel . textColor = UIColor . black
bodyLabel . numberOfLines = 0
bodyLabel . lineBreakMode = . byWordWrapping
bodyLabel . textAlignment = . center
// I m a g e
let imageView = UIImageView ( image : image )
view . addSubview ( imageView )
imageView . contentMode = . scaleAspectFit
let buttonTitle = NSLocalizedString ( " UPGRADE_EXPERIENCE_INTRODUCING_READ_RECEIPTS_PRIVACY_SETTINGS " , comment : " button label shown one time, after upgrade " )
let button = addButton ( title : buttonTitle ) { _ in
// d i s m i s s t h e m o d a l l y p r e s e n t e d v i e w c o n t r o l l e r , t h e n p r o c e e d .
self . experienceUpgradesPageViewController . dismiss ( animated : true ) {
guard let fromViewController = UIApplication . shared . frontmostViewController as ? HomeViewController else {
owsFail ( " unexpected frontmostViewController: \( String ( describing : UIApplication . shared . frontmostViewController ) ) " )
return
}
// C o n s t r u c t t h e " s e t t i n g s " v i e w & p u s h t h e " p r i v a c y s e t t i n g s " v i e w .
let navigationController = AppSettingsViewController . inModalNavigationController ( )
navigationController . pushViewController ( PrivacySettingsTableViewController ( ) , animated : false )
fromViewController . present ( navigationController , animated : true )
}
}
let bottomSpacer = UIView ( )
view . addSubview ( bottomSpacer )
// / L a y o u t V i e w s
// I m a g e l a y o u t
imageView . autoAlignAxis ( toSuperviewAxis : . vertical )
imageView . autoPinToSquareAspectRatio ( )
imageView . autoPinEdge ( . top , to : . bottom , of : titleLabel , withOffset : ScaleFromIPhone5To7Plus ( 36 , 40 ) )
imageView . autoSetDimension ( . height , toSize : ScaleFromIPhone5 ( 225 ) )
// T i t l e l a b e l l a y o u t
titleLabel . autoSetDimension ( . height , toSize : ScaleFromIPhone5 ( 40 ) )
titleLabel . autoPinWidthToSuperview ( withMargin : ScaleFromIPhone5To7Plus ( 16 , 24 ) )
titleLabel . autoPinTopToSuperview ( )
// B o d y l a b e l l a y o u t
bodyLabel . autoPinEdge ( . top , to : . bottom , of : imageView , withOffset : ScaleFromIPhone5To7Plus ( 18 , 28 ) )
bodyLabel . autoPinWidthToSuperview ( withMargin : bodyMargin )
bodyLabel . setContentHuggingVerticalHigh ( )
// B u t t o n l a y o u t
button . autoPinEdge ( . top , to : . bottom , of : bodyLabel , withOffset : ScaleFromIPhone5 ( 16 ) )
button . autoPinWidthToSuperview ( withMargin : ScaleFromIPhone5 ( 32 ) )
bottomSpacer . autoPinEdge ( . top , to : . bottom , of : button , withOffset : ScaleFromIPhone5 ( 16 ) )
bottomSpacer . autoPinEdge ( toSuperviewEdge : . bottom )
bottomSpacer . autoPinWidthToSuperview ( )
}
// MARK: - A c t i o n s
func addButton ( title : String , action : @ escaping ( UIButton ) -> Void ) -> UIButton {
self . buttonAction = action
let button = MultiLineButton ( )
view . addSubview ( button )
button . setTitle ( title , for : . normal )
button . setTitleColor ( UIColor . ows_signalBrandBlue , for : . normal )
button . isUserInteractionEnabled = true
button . addTarget ( self , action : #selector ( didTapButton ) , for : . touchUpInside )
button . contentEdgeInsets = UIEdgeInsets ( top : 10 , left : 10 , bottom : 10 , right : 10 )
button . titleLabel ? . textAlignment = . center
button . titleLabel ? . font = UIFont . ows_mediumFont ( withSize : ScaleFromIPhone5 ( 18 ) )
return button
}
func didTapButton ( sender : UIButton ) {
Logger . debug ( " \( TAG ) in \( #function ) " )
guard let buttonAction = self . buttonAction else {
owsFail ( " \( TAG ) button action was nil " )
return
}
buttonAction ( sender )
}
}
/* *
* Allows multiple lines of button text , and ensures the buttons intrinsic content size reflects that of it ' s label .
*/
class MultiLineButton : UIButton {
// MARK: - I n i t
required init ? ( coder aDecoder : NSCoder ) {
super . init ( coder : aDecoder )
self . commonInit ( )
}
required init ( ) {
super . init ( frame : CGRect . zero )
self . commonInit ( )
}
private func commonInit ( ) {
self . titleLabel ? . numberOfLines = 0
self . titleLabel ? . lineBreakMode = . byWordWrapping
}
// MARK: - O v e r r i d e s
override var intrinsicContentSize : CGSize {
guard let titleLabel = titleLabel else {
return CGSize . zero
}
// b e m o r e f o r g i v i n g w i t h t h e t a p p a b l e a r e a
let extraPadding : CGFloat = 20
let labelSize = titleLabel . intrinsicContentSize
return CGSize ( width : labelSize . width + extraPadding , height : labelSize . height + extraPadding )
}
override func layoutSubviews ( ) {
super . layoutSubviews ( )
titleLabel ? . preferredMaxLayoutWidth = titleLabel ? . frame . size . width ? ? 0
super . layoutSubviews ( )
}
}
private class IntroductingProfilesExperienceUpgradeViewController : ExperienceUpgradeViewController {
override func loadView ( ) {
self . view = UIView ( )
// / C r e a t e V i e w s
// T i t l e l a b e l
let titleLabel = UILabel ( )
view . addSubview ( titleLabel )
titleLabel . text = header
titleLabel . textAlignment = . center
titleLabel . font = UIFont . ows_regularFont ( withSize : ScaleFromIPhone5 ( 24 ) )
titleLabel . textColor = UIColor . white
titleLabel . minimumScaleFactor = 0.5
titleLabel . adjustsFontSizeToFitWidth = true
// B o d y l a b e l
let bodyLabel = UILabel ( )
self . bodyLabel = bodyLabel
view . addSubview ( bodyLabel )
bodyLabel . text = body
bodyLabel . font = UIFont . ows_lightFont ( withSize : ScaleFromIPhone5To7Plus ( 17 , 22 ) )
bodyLabel . textColor = UIColor . black
bodyLabel . numberOfLines = 0
bodyLabel . lineBreakMode = . byWordWrapping
bodyLabel . textAlignment = . center
// I m a g e
let imageView = UIImageView ( image : image )
view . addSubview ( imageView )
imageView . contentMode = . scaleAspectFit
// B u t t o n
let button = UIButton ( )
view . addSubview ( button )
let buttonTitle = NSLocalizedString ( " UPGRADE_EXPERIENCE_INTRODUCING_PROFILES_BUTTON " , comment : " button label shown one time, after user upgrades app " )
button . setTitle ( buttonTitle , for : . normal )
button . setTitleColor ( UIColor . white , for : . normal )
button . backgroundColor = UIColor . ows_materialBlue
button . isUserInteractionEnabled = true
button . addTarget ( self , action : #selector ( didTapButton ) , for : . touchUpInside )
button . contentEdgeInsets = UIEdgeInsets ( top : 10 , left : 20 , bottom : 10 , right : 20 )
button . titleLabel ? . font = UIFont . ows_mediumFont ( withSize : ScaleFromIPhone5 ( 18 ) )
// / L a y o u t V i e w s
// I m a g e l a y o u t
imageView . autoAlignAxis ( toSuperviewAxis : . vertical )
imageView . autoPinToSquareAspectRatio ( )
imageView . autoPinEdge ( . top , to : . bottom , of : titleLabel , withOffset : ScaleFromIPhone5To7Plus ( 36 , 40 ) )
imageView . autoSetDimension ( . height , toSize : ScaleFromIPhone5 ( 225 ) )
// T i t l e l a b e l l a y o u t
titleLabel . autoSetDimension ( . height , toSize : ScaleFromIPhone5 ( 40 ) )
titleLabel . autoPinWidthToSuperview ( withMargin : ScaleFromIPhone5To7Plus ( 16 , 24 ) )
titleLabel . autoPinEdge ( toSuperviewEdge : . top )
// B o d y l a b e l l a y o u t
bodyLabel . autoPinEdge ( . top , to : . bottom , of : imageView , withOffset : ScaleFromIPhone5To7Plus ( 18 , 28 ) )
bodyLabel . autoPinWidthToSuperview ( withMargin : bodyMargin )
bodyLabel . sizeToFit ( )
// B u t t o n l a y o u t
button . autoPinEdge ( . top , to : . bottom , of : bodyLabel , withOffset : ScaleFromIPhone5 ( 18 ) )
button . autoPinWidthToSuperview ( withMargin : ScaleFromIPhone5 ( 32 ) )
button . autoPinEdge ( toSuperviewEdge : . bottom , withInset : ScaleFromIPhone5 ( 16 ) )
button . autoSetDimension ( . height , toSize : ScaleFromIPhone5 ( 36 ) )
}
// MARK: - A c t i o n s
func didTapButton ( sender : UIButton ) {
Logger . debug ( " \( TAG ) in \( #function ) " )
// d i s m i s s t h e m o d a l l y p r e s e n t e d v i e w c o n t r o l l e r , t h e n p r o c e e d .
experienceUpgradesPageViewController . dismiss ( animated : true ) {
guard let fromViewController = UIApplication . shared . frontmostViewController as ? HomeViewController else {
owsFail ( " unexpected frontmostViewController: \( String ( describing : UIApplication . shared . frontmostViewController ) ) " )
return
}
ProfileViewController . presentForUpgradeOrNag ( from : fromViewController )
}
}
}
private class CallKitExperienceUpgradeViewController : ExperienceUpgradeViewController {
override func loadView ( ) {
super . loadView ( )
assert ( view != nil )
assert ( bodyLabel != nil )
// P r i v a c y S e t t i n g s B u t t o n
let privacySettingsButton = UIButton ( )
view . addSubview ( privacySettingsButton )
let privacyTitle = NSLocalizedString ( " UPGRADE_EXPERIENCE_CALLKIT_PRIVACY_SETTINGS_BUTTON " , comment : " button label shown once when when user upgrades app, in context of call kit " )
privacySettingsButton . setTitle ( privacyTitle , for : . normal )
privacySettingsButton . setTitleColor ( UIColor . ows_signalBrandBlue , for : . normal )
privacySettingsButton . isUserInteractionEnabled = true
privacySettingsButton . addTarget ( self , action : #selector ( didTapPrivacySettingsButton ) , for : . touchUpInside )
privacySettingsButton . titleLabel ? . font = bodyLabel . font
// P r i v a c y S e t t i n g s B u t t o n l a y o u t
privacySettingsButton . autoPinWidthToSuperview ( withMargin : bodyMargin )
privacySettingsButton . autoPinEdge ( . top , to : . bottom , of : bodyLabel , withOffset : ScaleFromIPhone5 ( 12 ) )
privacySettingsButton . sizeToFit ( )
}
// MARK: - A c t i o n s
func didTapPrivacySettingsButton ( sender : UIButton ) {
Logger . debug ( " \( TAG ) in \( #function ) " )
// d i s m i s s t h e m o d a l l y p r e s e n t e d v i e w c o n t r o l l e r , t h e n p r o c e e d .
experienceUpgradesPageViewController . dismiss ( animated : true ) {
let fromViewController = UIApplication . shared . frontmostViewController
assert ( fromViewController != nil )
// C o n s t r u c t t h e " s e t t i n g s " v i e w & p u s h t h e " p r i v a c y s e t t i n g s " v i e w .
let navigationController = AppSettingsViewController . inModalNavigationController ( )
navigationController . pushViewController ( PrivacySettingsTableViewController ( ) , animated : false )
fromViewController ? . present ( navigationController , animated : true , completion : nil )
}
}
}
private class ExperienceUpgradeViewController : OWSViewController {
let TAG = " [ExperienceUpgradeViewController] "
let header : String
let body : String
let image : UIImage ?
let experienceUpgradesPageViewController : ExperienceUpgradesPageViewController
var bodyLabel : UILabel !
let bodyMargin = ScaleFromIPhone5To7Plus ( 12 , 24 )
init ( experienceUpgrade : ExperienceUpgrade , experienceUpgradesPageViewController : ExperienceUpgradesPageViewController ) {
header = experienceUpgrade . title
body = experienceUpgrade . body
image = experienceUpgrade . image
self . experienceUpgradesPageViewController = experienceUpgradesPageViewController
super . init ( nibName : nil , bundle : nil )
}
required init ? ( coder aDecoder : NSCoder ) {
fatalError ( " init(coder:) has not been implemented " )
}
override func loadView ( ) {
self . view = UIView ( )
// / C r e a t e V i e w s
// T i t l e l a b e l
let titleLabel = UILabel ( )
view . addSubview ( titleLabel )
titleLabel . text = header
titleLabel . textAlignment = . center
titleLabel . font = UIFont . ows_regularFont ( withSize : ScaleFromIPhone5 ( 24 ) )
titleLabel . textColor = UIColor . white
titleLabel . minimumScaleFactor = 0.5
titleLabel . adjustsFontSizeToFitWidth = true
// B o d y l a b e l
let bodyLabel = UILabel ( )
self . bodyLabel = bodyLabel
view . addSubview ( bodyLabel )
bodyLabel . text = body
bodyLabel . font = UIFont . ows_lightFont ( withSize : ScaleFromIPhone5To7Plus ( 17 , 22 ) )
bodyLabel . textColor = UIColor . black
bodyLabel . numberOfLines = 0
bodyLabel . lineBreakMode = . byWordWrapping
bodyLabel . textAlignment = . center
// I m a g e
let imageView = UIImageView ( image : image )
view . addSubview ( imageView )
imageView . contentMode = . scaleAspectFit
// / L a y o u t V i e w s
// I m a g e l a y o u t
imageView . autoAlignAxis ( toSuperviewAxis : . vertical )
imageView . autoPinToSquareAspectRatio ( )
imageView . autoPinEdge ( . top , to : . bottom , of : titleLabel , withOffset : ScaleFromIPhone5To7Plus ( 36 , 60 ) )
imageView . autoSetDimension ( . height , toSize : ScaleFromIPhone5 ( 225 ) )
// T i t l e l a b e l l a y o u t
titleLabel . autoSetDimension ( . height , toSize : ScaleFromIPhone5 ( 40 ) )
titleLabel . autoPinWidthToSuperview ( withMargin : ScaleFromIPhone5To7Plus ( 16 , 24 ) )
titleLabel . autoPinEdge ( toSuperviewEdge : . top )
// B o d y l a b e l l a y o u t
bodyLabel . autoPinEdge ( . top , to : . bottom , of : imageView , withOffset : ScaleFromIPhone5To7Plus ( 18 , 28 ) )
bodyLabel . autoPinWidthToSuperview ( withMargin : bodyMargin )
bodyLabel . sizeToFit ( )
bodyLabel . autoPinEdge ( toSuperviewEdge : . bottom , withInset : ScaleFromIPhone5 ( 16 ) )
}
}
func setPageControlAppearance ( ) {
let pageControl = UIPageControl . appearance ( whenContainedInInstancesOf : [ UIPageViewController . self ] )
pageControl . pageIndicatorTintColor = UIColor . lightGray
pageControl . currentPageIndicatorTintColor = UIColor . ows_materialBlue
}
class ExperienceUpgradesPageViewController : OWSViewController , UIPageViewControllerDataSource {
let TAG = " [ExperienceUpgradeViewController] "
private let experienceUpgrades : [ ExperienceUpgrade ]
private var allViewControllers = [ UIViewController ] ( )
private var viewControllerIndexes = [ UIViewController : Int ] ( )
let pageViewController : UIPageViewController
// MARK: - I n i t i a l i z e r s
required init ( experienceUpgrades : [ ExperienceUpgrade ] ) {
self . experienceUpgrades = experienceUpgrades
setPageControlAppearance ( )
self . pageViewController = UIPageViewController ( transitionStyle : . scroll , navigationOrientation : . horizontal , options : nil )
super . init ( nibName : nil , bundle : nil )
self . pageViewController . dataSource = self
experienceUpgrades . forEach { addViewController ( experienceUpgrade : $0 ) }
}
@ available ( * , unavailable , message : " unavailable, use initWithExperienceUpgrade instead " )
required init ? ( coder aDecoder : NSCoder ) {
assert ( false )
// T h i s s h o u l d n e v e r h a p p e n , b u t s o a s n o t t o e x p l o d e w e g i v e s o m e b o g u s d a t a
self . experienceUpgrades = [ ExperienceUpgrade ( ) ]
self . pageViewController = UIPageViewController ( transitionStyle : . scroll , navigationOrientation : . horizontal , options : nil )
super . init ( coder : aDecoder )
self . pageViewController . dataSource = self
}
// MARK: - V i e w l i f e c y c l e
override func viewDidLoad ( ) {
guard let firstViewController = allViewControllers . first else {
owsFail ( " \( TAG ) no pages to show. " )
dismiss ( animated : true )
return
}
addDismissGesture ( )
self . pageViewController . setViewControllers ( [ firstViewController ] , direction : . forward , animated : false , completion : nil )
}
override func loadView ( ) {
self . view = UIView . container ( )
view . backgroundColor = UIColor . white
// / / C r e a t e V i e w s
// H e a d e r B a c k g r o u n d
let statusBarBackgroundView = UIView . container ( )
view . addSubview ( statusBarBackgroundView )
statusBarBackgroundView . backgroundColor = UIColor . ows_materialBlue
let headerBackgroundView = UIView . container ( )
view . addSubview ( headerBackgroundView )
headerBackgroundView . backgroundColor = UIColor . ows_materialBlue
// D i s m i s s b u t t o n
let dismissButton = UIButton ( )
view . addSubview ( dismissButton )
dismissButton . setTitle ( CommonStrings . dismissButton , for : . normal )
dismissButton . setTitleColor ( UIColor . ows_signalBrandBlue , for : . normal )
dismissButton . isUserInteractionEnabled = true
dismissButton . addTarget ( self , action : #selector ( didTapDismissButton ) , for : . touchUpInside )
dismissButton . titleLabel ? . font = UIFont . ows_mediumFont ( withSize : ScaleFromIPhone5 ( 16 ) )
let dismissInsetValue : CGFloat = ScaleFromIPhone5 ( 10 )
dismissButton . contentEdgeInsets = UIEdgeInsets ( top : dismissInsetValue , left : dismissInsetValue , bottom : dismissInsetValue , right : dismissInsetValue )
guard let carouselView = self . pageViewController . view else {
Logger . error ( " \( TAG ) carousel view was unexpectedly nil " )
return
}
self . view . addSubview ( carouselView )
// / / L a y o u t V i e w s
// S t a t u s B a r B a c k g r o u n d l a y o u t
//
// W e u s e a s e p a r a t e b a c k g r o u n d s f o r t h e " s t a t u s b a r " a r e a ( w h i c h h a s v e r y
// d i f f e r e n t h e i g h t o n i P h o n e X ) a n d t h e " h e a d e r " ( w h i c h h a s c o n s i s t e n t
// h e i g h t ) .
statusBarBackgroundView . autoPinWidthToSuperview ( )
statusBarBackgroundView . autoPinEdge ( toSuperviewEdge : . top )
statusBarBackgroundView . autoPinEdge ( . bottom , to : . top , of : headerBackgroundView )
// H e a d e r B a c k g r o u n d l a y o u t
statusBarBackgroundView . autoPinWidthToSuperview ( )
statusBarBackgroundView . autoPinEdge ( toSuperviewEdge : . top )
statusBarBackgroundView . autoPinEdge ( . bottom , to : . top , of : headerBackgroundView )
headerBackgroundView . autoPinWidthToSuperview ( )
headerBackgroundView . autoPinTopToSuperview ( )
headerBackgroundView . autoSetDimension ( . height , toSize : ScaleFromIPhone5 ( 60 ) )
// D i s m i s s b u t t o n l a y o u t
dismissButton . autoHCenterInSuperview ( )
dismissButton . autoPinBottomToSuperview ( withMargin : ScaleFromIPhone5 ( 10 ) )
// C a r o u s e l V i e w l a y o u t
carouselView . autoPinWidthToSuperview ( )
// n e g a t i v e i n s e t s o a s t o o v e r l a y t h e h e a d e r t e x t i n t h e c a r o u s e l v i e w w i t h t h e h e a d e r b a c k g r o u n d w h i c h
// l i v e s o u t s i d e o f t h e c a r o u s e l . W e d o t h i s s o t h a t t h e u s e r c a n ' t b o u n c e p a s t t h e p a g e v i e w c o n t r o l l e r s
// w i d t h l i m i t s , e x p o s i n g t h e e d g e o f t h e h e a d e r .
carouselView . autoPinTopToSuperview ( withMargin : ScaleFromIPhone5To7Plus ( 14 , 24 ) )
carouselView . autoPinEdge ( . bottom , to : . top , of : dismissButton , withOffset : ScaleFromIPhone5 ( - 10 ) )
}
private func addDismissGesture ( ) {
let swipeGesture = UISwipeGestureRecognizer ( target : self , action : #selector ( handleDismissGesture ) )
swipeGesture . direction = . down
view . addGestureRecognizer ( swipeGesture )
}
// MARK: - U I P a g e V i e w C o n t r o l l e r D a t a S o u r c e
public func pageViewController ( _ pageViewController : UIPageViewController , viewControllerAfter viewController : UIViewController ) -> UIViewController ? {
Logger . debug ( " \( TAG ) in \( #function ) " )
guard let currentIndex = self . viewControllerIndexes [ viewController ] else {
owsFail ( " \( TAG ) unknown view controller: \( viewController ) " )
return nil
}
if currentIndex + 1 = = allViewControllers . count {
// a l r e a d y a t l a s t v i e w c o n t r o l l e r
return nil
}
return allViewControllers [ currentIndex + 1 ]
}
public func pageViewController ( _ pageViewController : UIPageViewController , viewControllerBefore viewController : UIViewController ) -> UIViewController ? {
Logger . debug ( " \( TAG ) in \( #function ) " )
guard let currentIndex = self . viewControllerIndexes [ viewController ] else {
owsFail ( " \( TAG ) unknown view controller: \( viewController ) " )
return nil
}
if currentIndex <= 0 {
// a l r e a d y a t f i r s t v i e w c o n t r o l l e r
return nil
}
return allViewControllers [ currentIndex - 1 ]
}
public func presentationCount ( for pageViewController : UIPageViewController ) -> Int {
// d o n ' t s h o w a p a g e i n d i c a t o r i f t h e r e ' s o n l y o n e p a g e .
return allViewControllers . count = = 1 ? 0 : allViewControllers . count
}
public func presentationIndex ( for pageViewController : UIPageViewController ) -> Int {
guard let currentViewController = pageViewController . viewControllers ? . first else {
Logger . error ( " \( TAG ) unexpectedly empty view controllers. " )
return 0
}
guard let currentIndex = self . viewControllerIndexes [ currentViewController ] else {
Logger . error ( " \( TAG ) unknown view controller: \( currentViewController ) " )
return 0
}
return currentIndex
}
public func addViewController ( experienceUpgrade : ExperienceUpgrade ) {
guard let uniqueId = experienceUpgrade . uniqueId else {
Logger . error ( " \( self . TAG ) experienceUpgrade is missing uniqueId. " )
return
}
guard let identifier = ExperienceUpgradeId ( rawValue : uniqueId ) else {
owsFail ( " \( TAG ) unknown experience upgrade. skipping " )
return
}
let viewController : ExperienceUpgradeViewController = {
switch identifier {
case . callKit :
return CallKitExperienceUpgradeViewController ( experienceUpgrade : experienceUpgrade , experienceUpgradesPageViewController : self )
case . introducingProfiles :
return IntroductingProfilesExperienceUpgradeViewController ( experienceUpgrade : experienceUpgrade , experienceUpgradesPageViewController : self )
case . introducingReadReceipts :
return IntroductingReadReceiptsExperienceUpgradeViewController ( experienceUpgrade : experienceUpgrade , experienceUpgradesPageViewController : self )
case . introducingCustomNotificationAudio :
return IntroducingCustomNotificationAudioExperienceUpgradeViewController ( experienceUpgrade : experienceUpgrade , experienceUpgradesPageViewController : self )
default :
return ExperienceUpgradeViewController ( experienceUpgrade : experienceUpgrade , experienceUpgradesPageViewController : self )
}
} ( )
let count = allViewControllers . count
viewControllerIndexes [ viewController ] = count
allViewControllers . append ( viewController )
}
func didTapDismissButton ( sender : UIButton ) {
Logger . debug ( " \( TAG ) in \( #function ) " )
self . dismiss ( animated : true )
}
func handleDismissGesture ( sender : AnyObject ) {
Logger . debug ( " \( TAG ) in \( #function ) " )
self . dismiss ( animated : true )
}
}