2017-03-02 21:11:44 +01:00
//
2018-01-31 18:56:52 +01:00
// 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 .
2017-03-02 21:11:44 +01:00
//
import Foundation
2017-12-01 16:48:18 +01:00
import SignalMessaging
2017-03-02 21:11:44 +01:00
2018-02-26 21:03:07 +01:00
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 ) {
2018-03-06 18:27:04 +01:00
guard let fromViewController = UIApplication . shared . frontmostViewController else {
owsFail ( " frontmostViewController was unexectedly nil " )
2018-02-26 21:03:07 +01:00
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 ( )
2018-04-02 21:34:10 +02:00
navigationController . pushViewController ( NotificationSettingsViewController ( ) , animated : false )
2018-02-26 21:03:07 +01:00
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 ) )
2018-04-02 21:31:32 +02:00
titleLabel . autoPinTopToSuperviewMargin ( )
2018-02-26 21:03:07 +01:00
// 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
2018-04-02 21:34:10 +02:00
button . addTarget ( self , action : #selector ( didTapButton ) , for : . touchUpInside )
2018-02-26 21:03:07 +01:00
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 )
}
}
2017-09-27 20:30:17 +02:00
private class IntroductingReadReceiptsExperienceUpgradeViewController : ExperienceUpgradeViewController {
var buttonAction : ( ( UIButton ) -> Void ) ?
override func loadView ( ) {
2018-01-31 18:56:52 +01:00
self . view = UIView . container ( )
2017-09-27 20:30:17 +02:00
// / 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 ( )
2018-02-23 18:46:04 +01:00
navigationController . pushViewController ( PrivacySettingsTableViewController ( ) , animated : false )
2017-09-27 20:30:17 +02:00
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 ) )
2018-04-02 21:31:32 +02:00
titleLabel . autoPinTopToSuperviewMargin ( )
2017-09-27 20:30:17 +02:00
// 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 )
2017-12-20 05:38:37 +01:00
button . setTitleColor ( UIColor . ows_signalBrandBlue , for : . normal )
2017-09-27 20:30:17 +02:00
button . isUserInteractionEnabled = true
2018-02-23 18:46:04 +01:00
button . addTarget ( self , action : #selector ( didTapButton ) , for : . touchUpInside )
2017-09-27 20:30:17 +02:00
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 ( )
}
}
2017-09-02 00:08:31 +02:00
private class IntroductingProfilesExperienceUpgradeViewController : ExperienceUpgradeViewController {
override func loadView ( ) {
2017-09-05 16:32:30 +02:00
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
2017-09-02 00:08:31 +02:00
2017-09-02 02:00:34 +02:00
// B u t t o n
2017-09-02 00:08:31 +02:00
let button = UIButton ( )
view . addSubview ( button )
2017-09-02 02:00:34 +02:00
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 )
2017-12-20 05:38:37 +01:00
button . backgroundColor = UIColor . ows_materialBlue
2017-09-02 02:00:34 +02:00
2017-09-02 00:08:31 +02:00
button . isUserInteractionEnabled = true
2018-02-23 18:46:04 +01:00
button . addTarget ( self , action : #selector ( didTapButton ) , for : . touchUpInside )
2017-09-02 02:00:34 +02:00
button . contentEdgeInsets = UIEdgeInsets ( top : 10 , left : 20 , bottom : 10 , right : 20 )
2017-09-02 00:08:31 +02:00
2017-09-02 02:00:34 +02:00
button . titleLabel ? . font = UIFont . ows_mediumFont ( withSize : ScaleFromIPhone5 ( 18 ) )
2017-09-05 16:32:30 +02:00
// / 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 ( )
2017-09-02 02:00:34 +02:00
// 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 ) )
2017-09-05 16:32:30 +02:00
button . autoPinEdge ( toSuperviewEdge : . bottom , withInset : ScaleFromIPhone5 ( 16 ) )
button . autoSetDimension ( . height , toSize : ScaleFromIPhone5 ( 36 ) )
2017-09-02 00:08:31 +02:00
}
// 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 ) {
2017-09-06 19:59:39 +02:00
guard let fromViewController = UIApplication . shared . frontmostViewController as ? HomeViewController else {
2017-09-02 00:08:31 +02:00
owsFail ( " unexpected frontmostViewController: \( String ( describing : UIApplication . shared . frontmostViewController ) ) " )
return
}
ProfileViewController . presentForUpgradeOrNag ( from : fromViewController )
}
}
}
2017-03-02 21:11:44 +01:00
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 )
2017-12-20 05:38:37 +01:00
privacySettingsButton . setTitleColor ( UIColor . ows_signalBrandBlue , for : . normal )
2017-03-02 21:11:44 +01:00
privacySettingsButton . isUserInteractionEnabled = true
2018-02-23 18:46:04 +01:00
privacySettingsButton . addTarget ( self , action : #selector ( didTapPrivacySettingsButton ) , for : . touchUpInside )
2017-03-02 21:11:44 +01:00
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 .
2017-09-07 17:03:54 +02:00
let navigationController = AppSettingsViewController . inModalNavigationController ( )
2018-02-23 18:46:04 +01:00
navigationController . pushViewController ( PrivacySettingsTableViewController ( ) , animated : false )
2017-03-02 21:11:44 +01:00
fromViewController ? . present ( navigationController , animated : true , completion : nil )
}
}
}
2017-07-25 19:23:23 +02:00
private class ExperienceUpgradeViewController : OWSViewController {
2017-03-02 21:11:44 +01:00
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
2017-09-02 00:08:31 +02:00
titleLabel . font = UIFont . ows_regularFont ( withSize : ScaleFromIPhone5 ( 24 ) )
2017-03-02 21:11:44 +01:00
titleLabel . textColor = UIColor . white
titleLabel . minimumScaleFactor = 0.5
2017-05-24 15:33:17 +02:00
titleLabel . adjustsFontSizeToFitWidth = true
2017-03-02 21:11:44 +01:00
// 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
2017-09-05 16:32:30 +02:00
// 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 ) )
2017-03-02 21:11:44 +01:00
// T i t l e l a b e l l a y o u t
2017-09-05 16:32:30 +02:00
titleLabel . autoSetDimension ( . height , toSize : ScaleFromIPhone5 ( 40 ) )
2017-03-02 21:11:44 +01:00
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
2017-09-05 16:32:30 +02:00
bodyLabel . autoPinEdge ( . top , to : . bottom , of : imageView , withOffset : ScaleFromIPhone5To7Plus ( 18 , 28 ) )
2017-03-02 21:11:44 +01:00
bodyLabel . autoPinWidthToSuperview ( withMargin : bodyMargin )
bodyLabel . sizeToFit ( )
2017-09-05 16:32:30 +02:00
bodyLabel . autoPinEdge ( toSuperviewEdge : . bottom , withInset : ScaleFromIPhone5 ( 16 ) )
2017-03-02 21:11:44 +01:00
}
}
func setPageControlAppearance ( ) {
2018-02-23 18:46:04 +01:00
let pageControl = UIPageControl . appearance ( whenContainedInInstancesOf : [ UIPageViewController . self ] )
pageControl . pageIndicatorTintColor = UIColor . lightGray
pageControl . currentPageIndicatorTintColor = UIColor . ows_materialBlue
2017-03-02 21:11:44 +01:00
}
2017-07-25 19:23:23 +02:00
class ExperienceUpgradesPageViewController : OWSViewController , UIPageViewControllerDataSource {
2017-03-02 21:11:44 +01:00
let TAG = " [ExperienceUpgradeViewController] "
private let experienceUpgrades : [ ExperienceUpgrade ]
private var allViewControllers = [ UIViewController ] ( )
private var viewControllerIndexes = [ UIViewController : Int ] ( )
let pageViewController : UIPageViewController
2018-03-06 19:53:25 +01:00
let editingDBConnection : YapDatabaseConnection
2017-03-02 21:11:44 +01:00
// MARK: - I n i t i a l i z e r s
required init ( experienceUpgrades : [ ExperienceUpgrade ] ) {
self . experienceUpgrades = experienceUpgrades
setPageControlAppearance ( )
2018-03-06 22:43:33 +01:00
self . editingDBConnection = OWSPrimaryStorage . shared ( ) . newDatabaseConnection ( )
2018-02-23 18:46:04 +01:00
self . pageViewController = UIPageViewController ( transitionStyle : . scroll , navigationOrientation : . horizontal , options : nil )
2017-03-02 21:11:44 +01:00
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 ) {
2018-03-06 19:53:25 +01:00
fatalError ( " unimplemented " )
2017-03-02 21:11:44 +01:00
}
// MARK: - V i e w l i f e c y c l e
override func viewDidLoad ( ) {
guard let firstViewController = allViewControllers . first else {
2017-07-10 20:52:14 +02:00
owsFail ( " \( TAG ) no pages to show. " )
2017-03-02 21:11:44 +01:00
dismiss ( animated : true )
return
}
addDismissGesture ( )
self . pageViewController . setViewControllers ( [ firstViewController ] , direction : . forward , animated : false , completion : nil )
}
override func loadView ( ) {
2018-01-31 18:56:52 +01:00
self . view = UIView . container ( )
2017-03-02 21:11:44 +01:00
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
2018-01-31 18:56:52 +01:00
let statusBarBackgroundView = UIView . container ( )
view . addSubview ( statusBarBackgroundView )
statusBarBackgroundView . backgroundColor = UIColor . ows_materialBlue
let headerBackgroundView = UIView . container ( )
2017-03-02 21:11:44 +01:00
view . addSubview ( headerBackgroundView )
2017-12-20 05:38:37 +01:00
headerBackgroundView . backgroundColor = UIColor . ows_materialBlue
2017-03-02 21:11:44 +01:00
// D i s m i s s b u t t o n
let dismissButton = UIButton ( )
view . addSubview ( dismissButton )
2017-07-13 20:53:24 +02:00
dismissButton . setTitle ( CommonStrings . dismissButton , for : . normal )
2017-12-20 05:38:37 +01:00
dismissButton . setTitleColor ( UIColor . ows_signalBrandBlue , for : . normal )
2017-03-02 21:11:44 +01:00
dismissButton . isUserInteractionEnabled = true
2018-02-23 18:46:04 +01:00
dismissButton . addTarget ( self , action : #selector ( didTapDismissButton ) , for : . touchUpInside )
2017-09-02 02:00:34 +02:00
dismissButton . titleLabel ? . font = UIFont . ows_mediumFont ( withSize : ScaleFromIPhone5 ( 16 ) )
2017-03-02 21:11:44 +01:00
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
2018-01-31 18:56:52 +01:00
// 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 )
2017-03-02 21:11:44 +01:00
// H e a d e r B a c k g r o u n d l a y o u t
2018-01-31 18:56:52 +01:00
statusBarBackgroundView . autoPinWidthToSuperview ( )
statusBarBackgroundView . autoPinEdge ( toSuperviewEdge : . top )
statusBarBackgroundView . autoPinEdge ( . bottom , to : . top , of : headerBackgroundView )
2017-03-02 21:11:44 +01:00
headerBackgroundView . autoPinWidthToSuperview ( )
2018-04-02 21:31:32 +02:00
headerBackgroundView . autoPinTopToSuperviewMargin ( )
2018-01-31 18:56:52 +01:00
headerBackgroundView . autoSetDimension ( . height , toSize : ScaleFromIPhone5 ( 60 ) )
2017-03-02 21:11:44 +01:00
// D i s m i s s b u t t o n l a y o u t
dismissButton . autoHCenterInSuperview ( )
2018-04-02 21:31:32 +02:00
dismissButton . autoPinBottomToSuperviewMargin ( withInset : ScaleFromIPhone5 ( 10 ) )
2017-03-02 21:11:44 +01:00
// 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 .
2018-04-02 21:31:32 +02:00
carouselView . autoPinTopToSuperviewMargin ( withInset : ScaleFromIPhone5To7Plus ( 14 , 24 ) )
2017-03-02 21:11:44 +01:00
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 {
2017-07-10 20:52:14 +02:00
owsFail ( " \( TAG ) unknown view controller: \( viewController ) " )
2017-03-02 21:11:44 +01:00
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 {
2017-07-10 20:52:14 +02:00
owsFail ( " \( TAG ) unknown view controller: \( viewController ) " )
2017-03-02 21:11:44 +01:00
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 ) {
2017-11-15 19:15:48 +01:00
guard let uniqueId = experienceUpgrade . uniqueId else {
Logger . error ( " \( self . TAG ) experienceUpgrade is missing uniqueId. " )
return
}
guard let identifier = ExperienceUpgradeId ( rawValue : uniqueId ) else {
2017-07-10 20:52:14 +02:00
owsFail ( " \( TAG ) unknown experience upgrade. skipping " )
2017-03-02 21:11:44 +01:00
return
}
let viewController : ExperienceUpgradeViewController = {
switch identifier {
case . callKit :
return CallKitExperienceUpgradeViewController ( experienceUpgrade : experienceUpgrade , experienceUpgradesPageViewController : self )
2017-09-02 00:08:31 +02:00
case . introducingProfiles :
return IntroductingProfilesExperienceUpgradeViewController ( experienceUpgrade : experienceUpgrade , experienceUpgradesPageViewController : self )
2017-09-27 20:30:17 +02:00
case . introducingReadReceipts :
return IntroductingReadReceiptsExperienceUpgradeViewController ( experienceUpgrade : experienceUpgrade , experienceUpgradesPageViewController : self )
2018-02-26 21:03:07 +01:00
case . introducingCustomNotificationAudio :
return IntroducingCustomNotificationAudioExperienceUpgradeViewController ( experienceUpgrade : experienceUpgrade , experienceUpgradesPageViewController : self )
2017-03-02 21:11:44 +01:00
default :
return ExperienceUpgradeViewController ( experienceUpgrade : experienceUpgrade , experienceUpgradesPageViewController : self )
}
} ( )
let count = allViewControllers . count
viewControllerIndexes [ viewController ] = count
allViewControllers . append ( viewController )
}
2018-03-06 19:53:25 +01:00
override func dismiss ( animated flag : Bool , completion : ( ( ) -> Void ) ? = nil ) {
// B l o c k i n g w r i t e b e f o r e d i s m i s s , t o b e s u r e t h e y ' r e m a r k e d a s c o m p l e t e
// b e f o r e H o m e V i e w . d i d A p p e a r i s r e - f i r e d .
self . editingDBConnection . readWrite { transaction in
Logger . info ( " \( self . logTag ) marking all upgrades as seen. " )
ExperienceUpgradeFinder . shared . markAllAsSeen ( transaction : transaction )
}
super . dismiss ( animated : flag , completion : completion )
}
2017-03-02 21:11:44 +01:00
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 )
}
}