parent
2c25c25c2d
commit
175474e0d1
23
Signal/Images.xcassets/introductory_splash_read_receipts.imageset/Contents.json
vendored
Normal file
23
Signal/Images.xcassets/introductory_splash_read_receipts.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "signal-penguin-letter@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "signal-penguin-letter@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "signal-penguin-letter@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
Signal/Images.xcassets/introductory_splash_read_receipts.imageset/signal-penguin-letter@1x.png
vendored
Normal file
BIN
Signal/Images.xcassets/introductory_splash_read_receipts.imageset/signal-penguin-letter@1x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
BIN
Signal/Images.xcassets/introductory_splash_read_receipts.imageset/signal-penguin-letter@2x.png
vendored
Normal file
BIN
Signal/Images.xcassets/introductory_splash_read_receipts.imageset/signal-penguin-letter@2x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 98 KiB |
BIN
Signal/Images.xcassets/introductory_splash_read_receipts.imageset/signal-penguin-letter@3x.png
vendored
Normal file
BIN
Signal/Images.xcassets/introductory_splash_read_receipts.imageset/signal-penguin-letter@3x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 151 KiB |
|
@ -4,6 +4,160 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
private class IntroductingReadReceiptsExperienceUpgradeViewController: ExperienceUpgradeViewController {
|
||||
|
||||
var buttonAction: ((UIButton) -> Void)?
|
||||
|
||||
override func loadView() {
|
||||
self.view = UIView()
|
||||
|
||||
/// Create Views
|
||||
|
||||
// Title label
|
||||
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
|
||||
|
||||
// Body label
|
||||
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
|
||||
|
||||
// Image
|
||||
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
|
||||
// dismiss the modally presented view controller, then proceed.
|
||||
self.experienceUpgradesPageViewController.dismiss(animated: true) {
|
||||
guard let fromViewController = UIApplication.shared.frontmostViewController as? HomeViewController else {
|
||||
owsFail("unexpected frontmostViewController: \(String(describing: UIApplication.shared.frontmostViewController))")
|
||||
return
|
||||
}
|
||||
|
||||
// Construct the "settings" view & push the "privacy settings" view.
|
||||
let navigationController = AppSettingsViewController.inModalNavigationController()
|
||||
navigationController.pushViewController(PrivacySettingsTableViewController(), animated:false)
|
||||
|
||||
fromViewController.present(navigationController, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
let bottomSpacer = UIView()
|
||||
view.addSubview(bottomSpacer)
|
||||
|
||||
/// Layout Views
|
||||
|
||||
// Image layout
|
||||
imageView.autoAlignAxis(toSuperviewAxis: .vertical)
|
||||
imageView.autoPinToSquareAspectRatio()
|
||||
imageView.autoPinEdge(.top, to: .bottom, of: titleLabel, withOffset: ScaleFromIPhone5To7Plus(36, 40))
|
||||
imageView.autoSetDimension(.height, toSize: ScaleFromIPhone5(225))
|
||||
|
||||
// Title label layout
|
||||
titleLabel.autoSetDimension(.height, toSize: ScaleFromIPhone5(40))
|
||||
titleLabel.autoPinWidthToSuperview(withMargin: ScaleFromIPhone5To7Plus(16, 24))
|
||||
titleLabel.autoPinEdge(toSuperviewEdge: .top)
|
||||
|
||||
// Body label layout
|
||||
bodyLabel.autoPinEdge(.top, to: .bottom, of: imageView, withOffset: ScaleFromIPhone5To7Plus(18, 28))
|
||||
bodyLabel.autoPinWidthToSuperview(withMargin: bodyMargin)
|
||||
bodyLabel.setContentHuggingVerticalHigh()
|
||||
|
||||
// Button layout
|
||||
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: - Actions
|
||||
|
||||
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: - Init
|
||||
|
||||
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: - Overrides
|
||||
|
||||
override var intrinsicContentSize: CGSize {
|
||||
guard let titleLabel = titleLabel else {
|
||||
return CGSize.zero
|
||||
}
|
||||
|
||||
// be more forgiving with the tappable area
|
||||
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() {
|
||||
|
@ -383,6 +537,8 @@ class ExperienceUpgradesPageViewController: OWSViewController, UIPageViewControl
|
|||
return CallKitExperienceUpgradeViewController(experienceUpgrade: experienceUpgrade, experienceUpgradesPageViewController: self)
|
||||
case .introducingProfiles:
|
||||
return IntroductingProfilesExperienceUpgradeViewController(experienceUpgrade: experienceUpgrade, experienceUpgradesPageViewController: self)
|
||||
case .introducingReadReceipts:
|
||||
return IntroductingReadReceiptsExperienceUpgradeViewController(experienceUpgrade: experienceUpgrade, experienceUpgradesPageViewController: self)
|
||||
default:
|
||||
return ExperienceUpgradeViewController(experienceUpgrade: experienceUpgrade, experienceUpgradesPageViewController: self)
|
||||
}
|
||||
|
|
|
@ -490,7 +490,9 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
|
|||
{
|
||||
[super viewDidAppear:animated];
|
||||
|
||||
if (!self.newlyRegisteredUser && !self.viewHasEverAppeared) {
|
||||
if (self.newlyRegisteredUser) {
|
||||
[self markAllUpgradeExperiencesAsSeen];
|
||||
} else if (!self.viewHasEverAppeared) {
|
||||
[self displayAnyUnseenUpgradeExperience];
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@ import Foundation
|
|||
enum ExperienceUpgradeId: String {
|
||||
case videoCalling = "001",
|
||||
callKit = "002",
|
||||
introducingProfiles = "003"
|
||||
introducingProfiles = "003",
|
||||
introducingReadReceipts = "004"
|
||||
}
|
||||
|
||||
class ExperienceUpgradeFinder: NSObject {
|
||||
|
@ -34,6 +35,13 @@ class ExperienceUpgradeFinder: NSObject {
|
|||
image:#imageLiteral(resourceName: "introductory_splash_profile"))
|
||||
}
|
||||
|
||||
var introducingReadReceipts: ExperienceUpgrade {
|
||||
return ExperienceUpgrade(uniqueId: ExperienceUpgradeId.introducingReadReceipts.rawValue,
|
||||
title: NSLocalizedString("UPGRADE_EXPERIENCE_INTRODUCING_READ_RECEIPTS_TITLE", comment: "Header for upgrade experience"),
|
||||
body: NSLocalizedString("UPGRADE_EXPERIENCE_INTRODUCING_READ_RECEIPTS_DESCRIPTION", comment: "Description of new profile feature for upgrading (existing) users"),
|
||||
image:#imageLiteral(resourceName: "introductory_splash_read_receipts"))
|
||||
}
|
||||
|
||||
// Keep these ordered by increasing uniqueId.
|
||||
private var allExperienceUpgrades: [ExperienceUpgrade] {
|
||||
return [
|
||||
|
@ -43,7 +51,8 @@ class ExperienceUpgradeFinder: NSObject {
|
|||
//
|
||||
// videoCalling,
|
||||
// (UIDevice.current.supportsCallKit ? callKit : nil),
|
||||
introducingProfiles
|
||||
// introducingProfiles,
|
||||
introducingReadReceipts
|
||||
].flatMap { $0 }
|
||||
}
|
||||
|
||||
|
|
|
@ -1574,6 +1574,15 @@
|
|||
/* Header for upgrade experience */
|
||||
"UPGRADE_EXPERIENCE_INTRODUCING_PROFILES_TITLE" = "Ready for Your Closeup?";
|
||||
|
||||
/* Description of new profile feature for upgrading (existing) users */
|
||||
"UPGRADE_EXPERIENCE_INTRODUCING_READ_RECEIPTS_DESCRIPTION" = "You now have the option of seeing and sharing when messages have been read.";
|
||||
|
||||
/* button label shown one time, after upgrade */
|
||||
"UPGRADE_EXPERIENCE_INTRODUCING_READ_RECEIPTS_PRIVACY_SETTINGS" = "Enable read receipts in your privacy settings.";
|
||||
|
||||
/* Header for upgrade experience */
|
||||
"UPGRADE_EXPERIENCE_INTRODUCING_READ_RECEIPTS_TITLE" = "Introducing Read Receipts";
|
||||
|
||||
/* Description of video calling to upgrading (existing) users */
|
||||
"UPGRADE_EXPERIENCE_VIDEO_DESCRIPTION" = "Signal now supports secure video calling. Just start a call like normal, tap the camera button, and wave hello.";
|
||||
|
||||
|
|
Loading…
Reference in New Issue