Sketch out the onboarding splash view.

pull/2/head
Matthew Chen 6 years ago
parent 9fb08c1171
commit 54c8c1f352

@ -74,6 +74,8 @@
344825C6211390C800DB4BD8 /* OWSOrphanDataCleaner.m in Sources */ = {isa = PBXBuildFile; fileRef = 344825C5211390C800DB4BD8 /* OWSOrphanDataCleaner.m */; };
3448E15C22133274004B052E /* OnboardingPermissionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448E15B22133274004B052E /* OnboardingPermissionsViewController.swift */; };
3448E15E221333F5004B052E /* OnboardingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448E15D221333F5004B052E /* OnboardingController.swift */; };
3448E16022134C89004B052E /* OnboardingSplashViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448E15F22134C88004B052E /* OnboardingSplashViewController.swift */; };
3448E1622213585C004B052E /* OnboardingBaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448E1612213585C004B052E /* OnboardingBaseViewController.swift */; };
344F248D2007CCD600CFB4F4 /* DisplayableText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344F248C2007CCD600CFB4F4 /* DisplayableText.swift */; };
345BC30C2047030700257B7C /* OWS2FASettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 345BC30B2047030600257B7C /* OWS2FASettingsViewController.m */; };
3461284B1FD0B94000532771 /* SAELoadViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3461284A1FD0B93F00532771 /* SAELoadViewController.swift */; };
@ -727,6 +729,8 @@
344825C5211390C800DB4BD8 /* OWSOrphanDataCleaner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSOrphanDataCleaner.m; sourceTree = "<group>"; };
3448E15B22133274004B052E /* OnboardingPermissionsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingPermissionsViewController.swift; sourceTree = "<group>"; };
3448E15D221333F5004B052E /* OnboardingController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingController.swift; sourceTree = "<group>"; };
3448E15F22134C88004B052E /* OnboardingSplashViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingSplashViewController.swift; sourceTree = "<group>"; };
3448E1612213585C004B052E /* OnboardingBaseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingBaseViewController.swift; sourceTree = "<group>"; };
34491FC11FB0F78500B3E5A3 /* my */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = my; path = translations/my.lproj/Localizable.strings; sourceTree = "<group>"; };
344F248C2007CCD600CFB4F4 /* DisplayableText.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisplayableText.swift; sourceTree = "<group>"; };
345BC30A2047030600257B7C /* OWS2FASettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWS2FASettingsViewController.h; sourceTree = "<group>"; };
@ -1443,8 +1447,10 @@
3441FD9E21A3604F00BB9542 /* BackupRestoreViewController.swift */,
340FC879204DAC8C007AEB0F /* CodeVerificationViewController.h */,
340FC877204DAC8C007AEB0F /* CodeVerificationViewController.m */,
3448E1612213585C004B052E /* OnboardingBaseViewController.swift */,
3448E15D221333F5004B052E /* OnboardingController.swift */,
3448E15B22133274004B052E /* OnboardingPermissionsViewController.swift */,
3448E15F22134C88004B052E /* OnboardingSplashViewController.swift */,
346E9D5321B040B600562252 /* RegistrationController.swift */,
340FC878204DAC8C007AEB0F /* RegistrationViewController.h */,
340FC876204DAC8C007AEB0F /* RegistrationViewController.m */,
@ -3478,6 +3484,7 @@
D221A09A169C9E5E00537ABF /* main.m in Sources */,
3496957221A301A100DCFE74 /* OWSBackup.m in Sources */,
34B3F87B1E8DF1700035BE1A /* ExperienceUpgradesPageViewController.swift in Sources */,
3448E1622213585C004B052E /* OnboardingBaseViewController.swift in Sources */,
34E5DC8220D8050D00C08145 /* RegistrationUtils.m in Sources */,
452EA09E1EA7ABE00078744B /* AttachmentPointerView.swift in Sources */,
45638BDC1F3DD0D400128435 /* DebugUICalling.swift in Sources */,
@ -3510,6 +3517,7 @@
457C87B82032645C008D52D6 /* DebugUINotifications.swift in Sources */,
4C13C9F620E57BA30089A98B /* ColorPickerViewController.swift in Sources */,
4CC1ECFB211A553000CC13BE /* AppUpdateNag.swift in Sources */,
3448E16022134C89004B052E /* OnboardingSplashViewController.swift in Sources */,
34B6A903218B3F63007C4606 /* TypingIndicatorView.swift in Sources */,
458E38371D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m in Sources */,
34B6A905218B4C91007C4606 /* TypingIndicatorInteraction.swift in Sources */,

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "Screen Shot 2019-02-12 at 2.22.35 PM.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

@ -0,0 +1,75 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import UIKit
import PromiseKit
@objc
public class OnboardingBaseViewController: OWSViewController {
// Unlike a delegate, we can and should retain a strong reference to the OnboardingController.
let onboardingController: OnboardingController
@objc
public init(onboardingController: OnboardingController) {
self.onboardingController = onboardingController
super.init(nibName: nil, bundle: nil)
}
@available(*, unavailable, message: "use other init() instead.")
required public init?(coder aDecoder: NSCoder) {
notImplemented()
}
// MARK: -
func titleLabel(text: String) -> UILabel {
let titleLabel = UILabel()
titleLabel.text = text
titleLabel.textColor = Theme.primaryColor
titleLabel.font = UIFont.ows_dynamicTypeTitle2.ows_mediumWeight()
titleLabel.numberOfLines = 0
titleLabel.lineBreakMode = .byWordWrapping
titleLabel.textAlignment = .center
return titleLabel
}
func explanationLabel(explanationText: String, linkText: String, selector: Selector) -> UILabel {
let explanationText = NSAttributedString(string: explanationText)
.rtlSafeAppend(NSAttributedString(string: " "))
.rtlSafeAppend(linkText,
attributes: [
NSAttributedStringKey.foregroundColor: UIColor.ows_materialBlue
])
let explanationLabel = UILabel()
explanationLabel.textColor = Theme.secondaryColor
explanationLabel.font = UIFont.ows_dynamicTypeCaption1
explanationLabel.attributedText = explanationText
explanationLabel.numberOfLines = 0
explanationLabel.textAlignment = .center
explanationLabel.lineBreakMode = .byWordWrapping
explanationLabel.isUserInteractionEnabled = true
explanationLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: selector))
return explanationLabel
}
func button(title: String, selector: Selector) -> UIView {
// TODO: Make sure this all fits if dynamic font sizes are maxed out.
let buttonHeight: CGFloat = 48
let button = OWSFlatButton.button(title: title,
font: OWSFlatButton.fontForHeight(buttonHeight),
titleColor: .white,
backgroundColor: .ows_materialBlue,
target: self,
selector: selector)
button.autoSetDimension(.height, toSize: buttonHeight)
return button
}
// MARK: Orientation
public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
}

@ -6,6 +6,10 @@ import UIKit
@objc
public protocol OnboardingController: class {
func initialViewController() -> UIViewController
func onboardingSplashDidComplete(viewController: UIViewController)
func onboardingPermissionsWasSkipped(viewController: UIViewController)
func onboardingPermissionsDidComplete(viewController: UIViewController)
}
@ -13,8 +17,18 @@ public protocol OnboardingController: class {
// MARK: -
@objc
public class MockOnboardingController: NSObject, OnboardingController {
public class OnboardingControllerImpl: NSObject, OnboardingController {
public func initialViewController() -> UIViewController {
let view = OnboardingSplashViewController(onboardingController: self)
return view
}
public func onboardingSplashDidComplete(viewController: UIViewController) {
let view = OnboardingPermissionsViewController(onboardingController: self)
viewController.navigationController?.pushViewController(view, animated: true)
}
public func onboardingPermissionsWasSkipped(viewController: UIViewController) {}
public func onboardingPermissionsDidComplete(viewController: UIViewController) {}
}

@ -6,23 +6,7 @@ import UIKit
import PromiseKit
@objc
public class OnboardingPermissionsViewController: OWSViewController {
// Unlike a delegate, we can and should retain a strong reference to the OnboardingController.
private var onboardingController: OnboardingController
@objc
public init(onboardingController: OnboardingController) {
self.onboardingController = onboardingController
super.init(nibName: nil, bundle: nil)
}
@available(*, unavailable, message: "use other init() instead.")
required public init?(coder aDecoder: NSCoder) {
notImplemented()
}
// MARK: -
public class OnboardingPermissionsViewController: OnboardingBaseViewController {
override public func loadView() {
super.loadView()
@ -38,46 +22,25 @@ public class OnboardingPermissionsViewController: OWSViewController {
target: self,
action: #selector(skipWasPressed))
let titleLabel = UILabel()
titleLabel.text = NSLocalizedString("ONBOARDING_PERMISSIONS_TITLE", comment: "Title of the 'onboarding permissions' view.")
titleLabel.textColor = Theme.primaryColor
titleLabel.font = UIFont.ows_dynamicTypeTitle2.ows_mediumWeight()
titleLabel.numberOfLines = 0
titleLabel.lineBreakMode = .byWordWrapping
titleLabel.textAlignment = .center
let titleLabel = self.titleLabel(text: NSLocalizedString("ONBOARDING_PERMISSIONS_TITLE", comment: "Title of the 'onboarding permissions' view."))
view.addSubview(titleLabel)
titleLabel.autoPinEdges(toSuperviewMarginsExcludingEdge: .bottom)
let explainerLabel = UILabel()
// TODO: Finalize copy.
explainerLabel.text = NSLocalizedString("ONBOARDING_PERMISSIONS_EXPLANATION", comment: "Explanation in the 'onboarding permissions' view.")
explainerLabel.textColor = Theme.secondaryColor
explainerLabel.font = UIFont.ows_dynamicTypeCaption1
explainerLabel.numberOfLines = 0
explainerLabel.textAlignment = .center
explainerLabel.lineBreakMode = .byWordWrapping
explainerLabel.isUserInteractionEnabled = true
explainerLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(explainerLabelTapped)))
let explanationLabel = self.explanationLabel(explanationText: NSLocalizedString("ONBOARDING_PERMISSIONS_EXPLANATION",
comment: "Explanation in the 'onboarding permissions' view."),
linkText: NSLocalizedString("ONBOARDING_PERMISSIONS_LEARN_MORE_LINK",
comment: "Link to the 'learn more' in the 'onboarding permissions' view."),
selector: #selector(explanationLabelTapped))
// TODO: Make sure this all fits if dynamic font sizes are maxed out.
let buttonHeight: CGFloat = 48
let giveAccessButton = OWSFlatButton.button(title: NSLocalizedString("ONBOARDING_PERMISSIONS_GIVE_ACCESS_BUTTON",
comment: "Label for the 'give access' button in the 'onboarding permissions' view."),
font: OWSFlatButton.fontForHeight(buttonHeight),
titleColor: .white,
backgroundColor: .ows_materialBlue,
target: self,
selector: #selector(giveAccessPressed))
giveAccessButton.autoSetDimension(.height, toSize: buttonHeight)
let notNowButton = OWSFlatButton.button(title: NSLocalizedString("ONBOARDING_PERMISSIONS_GIVE_ACCESS_BUTTON",
comment: "Label for the 'give access' button in the 'onboarding permissions' view."),
font: OWSFlatButton.fontForHeight(buttonHeight),
titleColor: .white,
backgroundColor: .ows_materialBlue,
target: self,
selector: #selector(notNowPressed))
notNowButton.autoSetDimension(.height, toSize: buttonHeight)
let giveAccessButton = self.button(title: NSLocalizedString("ONBOARDING_PERMISSIONS_GIVE_ACCESS_BUTTON",
comment: "Label for the 'give access' button in the 'onboarding permissions' view."),
selector: #selector(giveAccessPressed))
let notNowButton = self.button(title: NSLocalizedString("ONBOARDING_PERMISSIONS_NOT_NOW_BUTTON",
comment: "Label for the 'not now' button in the 'onboarding permissions' view."),
selector: #selector(notNowPressed))
let buttonStack = UIStackView(arrangedSubviews: [
giveAccessButton,
@ -88,7 +51,7 @@ public class OnboardingPermissionsViewController: OWSViewController {
buttonStack.spacing = 12
let stackView = UIStackView(arrangedSubviews: [
explainerLabel,
explanationLabel,
buttonStack
])
stackView.axis = .vertical
@ -146,12 +109,6 @@ public class OnboardingPermissionsViewController: OWSViewController {
return promise
}
// MARK: Orientation
public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
// MARK: - Events
@objc func skipWasPressed() {
@ -160,7 +117,7 @@ public class OnboardingPermissionsViewController: OWSViewController {
onboardingController.onboardingPermissionsWasSkipped(viewController: self)
}
@objc func explainerLabelTapped(sender: UIGestureRecognizer) {
@objc func explanationLabelTapped(sender: UIGestureRecognizer) {
guard sender.state == .recognized else {
return
}

@ -0,0 +1,91 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import UIKit
import PromiseKit
@objc
public class OnboardingSplashViewController: OnboardingBaseViewController {
override public func loadView() {
super.loadView()
view.backgroundColor = Theme.backgroundColor
view.layoutMargins = .zero
// TODO:
// navigationItem.title = NSLocalizedString("SETTINGS_BACKUP", comment: "Label for the backup view in app settings.")
let heroImage = UIImage(named: "onboarding_splash_hero")
let heroImageView = UIImageView(image: heroImage)
heroImageView.contentMode = .scaleAspectFit
heroImageView.layer.minificationFilter = kCAFilterTrilinear
heroImageView.layer.magnificationFilter = kCAFilterTrilinear
heroImageView.setCompressionResistanceLow()
heroImageView.setContentHuggingVerticalLow()
let titleLabel = self.titleLabel(text: NSLocalizedString("ONBOARDING_SPLASH_TITLE", comment: "Title of the 'onboarding splash' view."))
view.addSubview(titleLabel)
titleLabel.autoPinWidthToSuperviewMargins()
titleLabel.autoPinEdge(toSuperviewMargin: .top)
// TODO: Finalize copy.
let explanationLabel = self.explanationLabel(explanationText: NSLocalizedString("ONBOARDING_SPLASH_EXPLANATION",
comment: "Explanation in the 'onboarding splash' view."),
linkText: NSLocalizedString("ONBOARDING_SPLASH_TERM_AND_PRIVACY_POLICY",
comment: "Link to the 'terms and privacy policy' in the 'onboarding splash' view."),
selector: #selector(explanationLabelTapped))
// TODO: Make sure this all fits if dynamic font sizes are maxed out.
let continueButton = self.button(title: NSLocalizedString("BUTTON_CONTINUE",
comment: "Label for 'continue' button."),
selector: #selector(continuePressed))
view.addSubview(continueButton)
let stackView = UIStackView(arrangedSubviews: [
heroImageView,
UIView.spacer(withHeight: 22),
titleLabel,
UIView.spacer(withHeight: 56),
explanationLabel,
UIView.spacer(withHeight: 40),
continueButton
])
stackView.axis = .vertical
stackView.alignment = .fill
stackView.layoutMargins = UIEdgeInsets(top: 32, left: 32, bottom: 32, right: 32)
stackView.isLayoutMarginsRelativeArrangement = true
view.addSubview(stackView)
stackView.autoPinWidthToSuperviewMargins()
stackView.autoPin(toTopLayoutGuideOf: self, withInset: 0)
stackView.autoPin(toBottomLayoutGuideOf: self, withInset: 0)
}
public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.isNavigationBarHidden = true
}
public override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.navigationController?.isNavigationBarHidden = true
}
// MARK: - Events
@objc func explanationLabelTapped(sender: UIGestureRecognizer) {
guard sender.state == .recognized else {
return
}
// TODO:
}
@objc func continuePressed() {
Logger.info("")
onboardingController.onboardingSplashDidComplete(viewController: self)
}
}

@ -1496,6 +1496,30 @@
/* No comment provided by engineer. */
"OK" = "OK";
/* Explanation in the 'onboarding permissions' view. */
"ONBOARDING_PERMISSIONS_EXPLANATION" = "ONBOARDING_PERMISSIONS_EXPLANATION";
/* Label for the 'give access' button in the 'onboarding permissions' view. */
"ONBOARDING_PERMISSIONS_GIVE_ACCESS_BUTTON" = "Give Access";
/* Link to the 'learn more' in the 'onboarding permissions' view. */
"ONBOARDING_PERMISSIONS_LEARN_MORE_LINK" = "Learn More";
/* Label for the 'not now' button in the 'onboarding permissions' view. */
"ONBOARDING_PERMISSIONS_NOT_NOW_BUTTON" = "Not Now";
/* Title of the 'onboarding permissions' view. */
"ONBOARDING_PERMISSIONS_TITLE" = "We need access to your contacts and notifications";
/* Explanation in the 'onboarding splash' view. */
"ONBOARDING_SPLASH_EXPLANATION" = "By continuing, you agree to Signal's terms.";
/* Link to the 'terms and privacy policy' in the 'onboarding splash' view. */
"ONBOARDING_SPLASH_TERM_AND_PRIVACY_POLICY" = "Terms and Privacy Policy";
/* Title of the 'onboarding splash' view. */
"ONBOARDING_SPLASH_TITLE" = "Signal is the private messenger for everybody";
/* Button text which opens the settings app */
"OPEN_SETTINGS_BUTTON" = "Settings";

@ -72,4 +72,18 @@ extension UIView {
return nil
}
}
@objc
public class func spacer(withWidth width: CGFloat) -> UIView {
let view = UIView()
view.autoSetDimension(.width, toSize: width)
return view
}
@objc
public class func spacer(withHeight height: CGFloat) -> UIView {
let view = UIView()
view.autoSetDimension(.height, toSize: height)
return view
}
}

Loading…
Cancel
Save