Merge branch 'nt/profile-name-reminder'
This commit is contained in:
commit
ceae3f1f3d
@ -632,8 +632,7 @@
|
||||
8889007123DBB39B00F40186 /* reactionMegaphone_6.png in Resources */ = {isa = PBXBuildFile; fileRef = 8889006923DBB39B00F40186 /* reactionMegaphone_6.png */; };
|
||||
8889007223DBB39B00F40186 /* reactionMegaphone_4.png in Resources */ = {isa = PBXBuildFile; fileRef = 8889006A23DBB39B00F40186 /* reactionMegaphone_4.png */; };
|
||||
8889007323DBB39B00F40186 /* reactionMegaphone_5.png in Resources */ = {isa = PBXBuildFile; fileRef = 8889006B23DBB39B00F40186 /* reactionMegaphone_5.png */; };
|
||||
8889007523DBD0B400F40186 /* RequiredProfileNames.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8889007423DBD0B400F40186 /* RequiredProfileNames.swift */; };
|
||||
8889007723DBD61200F40186 /* requiredProfileNamesSplash.json in Resources */ = {isa = PBXBuildFile; fileRef = 8889007623DBD61200F40186 /* requiredProfileNamesSplash.json */; };
|
||||
8889007523DBD0B400F40186 /* ProfileNameReminder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8889007423DBD0B400F40186 /* ProfileNameReminder.swift */; };
|
||||
888C828223D795FA0059464B /* pinCreationFail.json in Resources */ = {isa = PBXBuildFile; fileRef = 888C827F23D795F90059464B /* pinCreationFail.json */; };
|
||||
888C828323D795FA0059464B /* pinCreationInProgress.json in Resources */ = {isa = PBXBuildFile; fileRef = 888C828023D795FA0059464B /* pinCreationInProgress.json */; };
|
||||
88905E9E229CCA96004E4234 /* ExpirationNagView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88905E9D229CCA96004E4234 /* ExpirationNagView.swift */; };
|
||||
@ -1514,8 +1513,7 @@
|
||||
8889006923DBB39B00F40186 /* reactionMegaphone_6.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = reactionMegaphone_6.png; sourceTree = "<group>"; };
|
||||
8889006A23DBB39B00F40186 /* reactionMegaphone_4.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = reactionMegaphone_4.png; sourceTree = "<group>"; };
|
||||
8889006B23DBB39B00F40186 /* reactionMegaphone_5.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = reactionMegaphone_5.png; sourceTree = "<group>"; };
|
||||
8889007423DBD0B400F40186 /* RequiredProfileNames.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequiredProfileNames.swift; sourceTree = "<group>"; };
|
||||
8889007623DBD61200F40186 /* requiredProfileNamesSplash.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = requiredProfileNamesSplash.json; sourceTree = "<group>"; };
|
||||
8889007423DBD0B400F40186 /* ProfileNameReminder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileNameReminder.swift; sourceTree = "<group>"; };
|
||||
888C827F23D795F90059464B /* pinCreationFail.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = pinCreationFail.json; sourceTree = "<group>"; };
|
||||
888C828023D795FA0059464B /* pinCreationInProgress.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = pinCreationInProgress.json; sourceTree = "<group>"; };
|
||||
88905E9D229CCA96004E4234 /* ExpirationNagView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpirationNagView.swift; sourceTree = "<group>"; };
|
||||
@ -2965,7 +2963,7 @@
|
||||
children = (
|
||||
88A505F923DBA1360005C012 /* IntroducingPINs.swift */,
|
||||
88A505FB23DBAE4F0005C012 /* Reactions.swift */,
|
||||
8889007423DBD0B400F40186 /* RequiredProfileNames.swift */,
|
||||
8889007423DBD0B400F40186 /* ProfileNameReminder.swift */,
|
||||
);
|
||||
path = "Upgrade Views";
|
||||
sourceTree = "<group>";
|
||||
@ -2982,7 +2980,6 @@
|
||||
888C827F23D795F90059464B /* pinCreationFail.json */,
|
||||
888C828023D795FA0059464B /* pinCreationInProgress.json */,
|
||||
8837F73C23D8DE8400772A32 /* pinCreationSuccess.json */,
|
||||
8889007623DBD61200F40186 /* requiredProfileNamesSplash.json */,
|
||||
);
|
||||
path = Lottie;
|
||||
sourceTree = "<group>";
|
||||
@ -3644,7 +3641,6 @@
|
||||
45B74A7F2044AAB600CD42F8 /* note-quiet.aifc in Resources */,
|
||||
4C9D349B2369F11F006A4307 /* notificationPermission1.png in Resources */,
|
||||
45B74A842044AAB600CD42F8 /* popcorn.aifc in Resources */,
|
||||
8889007723DBD61200F40186 /* requiredProfileNamesSplash.json in Resources */,
|
||||
45B74A7D2044AAB600CD42F8 /* popcorn-quiet.aifc in Resources */,
|
||||
45B74A822044AAB600CD42F8 /* pulse.aifc in Resources */,
|
||||
4C9D349D2369F11F006A4307 /* notificationPermission2.png in Resources */,
|
||||
@ -4416,7 +4412,7 @@
|
||||
34EA69402194933900702471 /* MediaDownloadView.swift in Sources */,
|
||||
340FC8AB204DAC8D007AEB0F /* DomainFrontingCountryViewController.m in Sources */,
|
||||
4C586926224FAB83003FD070 /* AVAudioSession+OWS.m in Sources */,
|
||||
8889007523DBD0B400F40186 /* RequiredProfileNames.swift in Sources */,
|
||||
8889007523DBD0B400F40186 /* ProfileNameReminder.swift in Sources */,
|
||||
3496744D2076768700080B5F /* OWSMessageBubbleView.m in Sources */,
|
||||
34B3F8751E8DF1700035BE1A /* CallViewController.swift in Sources */,
|
||||
4C4AE6A1224AF35700D4AF6F /* SendMediaNavigationController.swift in Sources */,
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -57,8 +57,7 @@ class ExperienceUpgradeManager: NSObject {
|
||||
|
||||
private static func hasSplash(forExperienceUpgrade experienceUpgrade: ExperienceUpgrade) -> Bool {
|
||||
switch experienceUpgrade.id {
|
||||
case .introducingPins,
|
||||
.requiredProfileNames:
|
||||
case .introducingPins:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
@ -70,9 +69,6 @@ class ExperienceUpgradeManager: NSObject {
|
||||
case .introducingPins:
|
||||
let vc = IntroducingPinsSplash(experienceUpgrade: experienceUpgrade)
|
||||
return OWSNavigationController(rootViewController: vc)
|
||||
case .requiredProfileNames:
|
||||
let vc = RequiredProfileNamesSplash(experienceUpgrade: experienceUpgrade)
|
||||
return OWSNavigationController(rootViewController: vc)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
@ -84,7 +80,7 @@ class ExperienceUpgradeManager: NSObject {
|
||||
switch experienceUpgrade.id {
|
||||
case .introducingPins,
|
||||
.reactions,
|
||||
.requiredProfileNames:
|
||||
.profileNameReminder:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
@ -97,8 +93,8 @@ class ExperienceUpgradeManager: NSObject {
|
||||
return IntroducingPinsMegaphone(experienceUpgrade: experienceUpgrade, fromViewController: fromViewController)
|
||||
case .reactions:
|
||||
return ReactionsMegaphone(experienceUpgrade: experienceUpgrade, fromViewController: fromViewController)
|
||||
case .requiredProfileNames:
|
||||
return RequiredProfileNamesMegaphone(experienceUpgrade: experienceUpgrade, fromViewController: fromViewController)
|
||||
case .profileNameReminder:
|
||||
return ProfileNameReminderMegaphone(experienceUpgrade: experienceUpgrade, fromViewController: fromViewController)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
//
|
||||
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Lottie
|
||||
|
||||
class ProfileNameReminderMegaphone: MegaphoneView {
|
||||
init(experienceUpgrade: ExperienceUpgrade, fromViewController: UIViewController) {
|
||||
super.init(experienceUpgrade: experienceUpgrade)
|
||||
|
||||
let hasProfileNameAlready = OWSProfileManager.shared().localFullName()?.isEmpty == false
|
||||
|
||||
titleText = hasProfileNameAlready
|
||||
? NSLocalizedString("REQUIRE_PROFILE_NAMES_MEGAPHONE_HAS_NAME_TITLE",
|
||||
comment: "Title for required profile name megaphone when user already has a profile name")
|
||||
: NSLocalizedString("REQUIRE_PROFILE_NAMES_MEGAPHONE_NO_NAME_TITLE",
|
||||
comment: "Title for required profile name megaphone when user doesn't have a profile name")
|
||||
bodyText = hasProfileNameAlready
|
||||
? NSLocalizedString("REQUIRE_PROFILE_NAMES_MEGAPHONE_HAS_NAME_BODY",
|
||||
comment: "Body for required profile name megaphone when user already has a profile name")
|
||||
: NSLocalizedString("REQUIRE_PROFILE_NAMES_MEGAPHONE_NO_NAME_BODY",
|
||||
comment: "Body for required profile name megaphone when user doesn't have a profile name")
|
||||
imageName = "profileMegaphone"
|
||||
|
||||
let primaryButton = MegaphoneView.Button(
|
||||
title: NSLocalizedString("REQUIRE_PROFILE_NAMES_MEGAPHONE_ACTION",
|
||||
comment: "Action text for required profile name megaphone")
|
||||
) { [weak self] in
|
||||
let vc = ProfileViewController.forExperienceUpgrade {
|
||||
self?.markAsComplete()
|
||||
fromViewController.navigationController?.popToViewController(fromViewController, animated: true) {
|
||||
fromViewController.navigationController?.setNavigationBarHidden(false, animated: false)
|
||||
self?.dismiss(animated: false)
|
||||
self?.presentToast(
|
||||
text: NSLocalizedString("REQUIRE_PROFILE_NAMES_MEGAPHONE_TOAST",
|
||||
comment: "Toast indicating that a PIN has been created."),
|
||||
fromViewController: fromViewController
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fromViewController.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
let secondaryButton = snoozeButton(fromViewController: fromViewController)
|
||||
setButtons(primary: primaryButton, secondary: secondaryButton)
|
||||
}
|
||||
|
||||
required init(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
@ -1,188 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Lottie
|
||||
|
||||
class RequiredProfileNamesMegaphone: MegaphoneView {
|
||||
init(experienceUpgrade: ExperienceUpgrade, fromViewController: UIViewController) {
|
||||
super.init(experienceUpgrade: experienceUpgrade)
|
||||
|
||||
let hasProfileNameAlready = OWSProfileManager.shared().localFullName()?.isEmpty == false
|
||||
|
||||
titleText = hasProfileNameAlready
|
||||
? NSLocalizedString("REQUIRE_PROFILE_NAMES_MEGAPHONE_HAS_NAME_TITLE",
|
||||
comment: "Title for required profile name megaphone when user already has a profile name")
|
||||
: NSLocalizedString("REQUIRE_PROFILE_NAMES_MEGAPHONE_NO_NAME_TITLE",
|
||||
comment: "Title for required profile name megaphone when user doesn't have a profile name")
|
||||
bodyText = hasProfileNameAlready
|
||||
? NSLocalizedString("REQUIRE_PROFILE_NAMES_MEGAPHONE_HAS_NAME_BODY",
|
||||
comment: "Body for required profile name megaphone when user already has a profile name")
|
||||
: NSLocalizedString("REQUIRE_PROFILE_NAMES_MEGAPHONE_NO_NAME_BODY",
|
||||
comment: "Body for required profile name megaphone when user doesn't have a profile name")
|
||||
imageName = "profileMegaphone"
|
||||
|
||||
let primaryButton = MegaphoneView.Button(
|
||||
title: NSLocalizedString("REQUIRE_PROFILE_NAMES_MEGAPHONE_ACTION",
|
||||
comment: "Action text for required profile name megaphone")
|
||||
) { [weak self] in
|
||||
let vc = ProfileViewController.forExperienceUpgrade {
|
||||
self?.markAsComplete()
|
||||
fromViewController.navigationController?.popToViewController(fromViewController, animated: true) {
|
||||
fromViewController.navigationController?.setNavigationBarHidden(false, animated: false)
|
||||
self?.dismiss(animated: false)
|
||||
self?.presentToast(
|
||||
text: NSLocalizedString("REQUIRE_PROFILE_NAMES_MEGAPHONE_TOAST",
|
||||
comment: "Toast indicating that a PIN has been created."),
|
||||
fromViewController: fromViewController
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fromViewController.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
let secondaryButton = snoozeButton(fromViewController: fromViewController)
|
||||
setButtons(primary: primaryButton, secondary: secondaryButton)
|
||||
}
|
||||
|
||||
required init(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
class RequiredProfileNamesSplash: SplashViewController {
|
||||
|
||||
let animationView = AnimationView(name: "requiredProfileNamesSplash")
|
||||
|
||||
var ows2FAManager: OWS2FAManager {
|
||||
return .shared()
|
||||
}
|
||||
|
||||
var hasProfileNameAlready: Bool {
|
||||
return OWSProfileManager.shared().localFullName()?.isEmpty == false
|
||||
}
|
||||
|
||||
override var canDismissWithGesture: Bool { return false }
|
||||
|
||||
// MARK: - View lifecycle
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
animationView.play()
|
||||
navigationController?.setNavigationBarHidden(true, animated: false)
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
navigationController?.setNavigationBarHidden(false, animated: false)
|
||||
}
|
||||
|
||||
override func loadView() {
|
||||
|
||||
self.view = UIView.container()
|
||||
self.view.backgroundColor = Theme.backgroundColor
|
||||
|
||||
animationView.contentMode = .scaleAspectFit
|
||||
animationView.loopMode = .playOnce
|
||||
animationView.backgroundBehavior = .forceFinish
|
||||
|
||||
view.addSubview(animationView)
|
||||
animationView.autoPinTopToSuperviewMargin(withInset: 10)
|
||||
animationView.autoPinWidthToSuperview()
|
||||
animationView.setContentHuggingLow()
|
||||
animationView.setCompressionResistanceLow()
|
||||
|
||||
let title: String
|
||||
let body: String
|
||||
|
||||
if hasProfileNameAlready {
|
||||
title = NSLocalizedString("REQUIRE_PROFILE_NAMES_SPLASH_CONFIRMATION_TITLE",
|
||||
comment: "Header for required profile names splash screen when the user already has a profile name")
|
||||
body = NSLocalizedString("REQUIRE_PROFILE_NAMES_SPLASH_CONFIRMATION_DESCRIPTION",
|
||||
comment: "Body text for required profile names splash screen when the user already has a profile name")
|
||||
} else {
|
||||
title = NSLocalizedString("REQUIRE_PROFILE_NAMES_SPLASH_CREATION_TITLE",
|
||||
comment: "Header for required profile names splash screen when the user doesn't have a profile name")
|
||||
body = NSLocalizedString("REQUIRE_PROFILE_NAMES_SPLASH_CREATION_DESCRIPTION",
|
||||
comment: "Body text for required profile names splash screen when the user doesn't have a profile name")
|
||||
}
|
||||
|
||||
let hMargin: CGFloat = ScaleFromIPhone5To7Plus(16, 24)
|
||||
|
||||
// Title label
|
||||
let titleLabel = UILabel()
|
||||
titleLabel.text = title
|
||||
titleLabel.textAlignment = .center
|
||||
titleLabel.font = UIFont.ows_dynamicTypeTitle1.ows_semibold()
|
||||
titleLabel.textColor = Theme.primaryTextColor
|
||||
titleLabel.minimumScaleFactor = 0.5
|
||||
titleLabel.adjustsFontSizeToFitWidth = true
|
||||
view.addSubview(titleLabel)
|
||||
titleLabel.autoPinWidthToSuperview(withMargin: hMargin)
|
||||
// The title label actually overlaps the hero image because it has a long shadow
|
||||
// and we want the text to partially sit on top of this.
|
||||
titleLabel.autoPinEdge(.top, to: .bottom, of: animationView, withOffset: -10)
|
||||
titleLabel.setContentHuggingVerticalHigh()
|
||||
|
||||
// Body label
|
||||
let bodyLabel = UILabel()
|
||||
bodyLabel.text = body
|
||||
bodyLabel.font = UIFont.ows_dynamicTypeBody
|
||||
bodyLabel.textColor = Theme.primaryTextColor
|
||||
bodyLabel.numberOfLines = 0
|
||||
bodyLabel.lineBreakMode = .byWordWrapping
|
||||
bodyLabel.textAlignment = .center
|
||||
view.addSubview(bodyLabel)
|
||||
bodyLabel.autoPinWidthToSuperview(withMargin: hMargin)
|
||||
bodyLabel.autoPinEdge(.top, to: .bottom, of: titleLabel, withOffset: 6)
|
||||
bodyLabel.setContentHuggingVerticalHigh()
|
||||
|
||||
// Primary button
|
||||
let primaryButton = OWSFlatButton.button(title: primaryButtonTitle(),
|
||||
font: UIFont.ows_dynamicTypeBody.ows_semibold(),
|
||||
titleColor: .white,
|
||||
backgroundColor: .ows_signalBlue,
|
||||
target: self,
|
||||
selector: #selector(didTapPrimaryButton))
|
||||
primaryButton.autoSetHeightUsingFont()
|
||||
view.addSubview(primaryButton)
|
||||
|
||||
primaryButton.autoPinWidthToSuperview(withMargin: hMargin)
|
||||
primaryButton.autoPinEdge(.top, to: .bottom, of: bodyLabel, withOffset: 28)
|
||||
primaryButton.setContentHuggingVerticalHigh()
|
||||
primaryButton.autoPinBottomToSuperviewMargin(withInset: ScaleFromIPhone5(10))
|
||||
}
|
||||
|
||||
@objc
|
||||
func didTapPrimaryButton(_ sender: UIButton) {
|
||||
let vc = ProfileViewController.forExperienceUpgrade { [weak self] in
|
||||
self?.dismiss(animated: true)
|
||||
}
|
||||
navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
func primaryButtonTitle() -> String {
|
||||
return hasProfileNameAlready
|
||||
? NSLocalizedString("REQUIRE_PROFILE_NAMES_SPLASH_CONFIRMATION_BUTTON",
|
||||
comment: "Button to start a confirm profile name flow from the one time splash screen that appears after upgrading")
|
||||
: NSLocalizedString("REQUIRE_PROFILE_NAMES_SPLASH_CREATION_BUTTON",
|
||||
comment: "Button to start a create profile name flow from the one time splash screen that appears after upgrading")
|
||||
}
|
||||
|
||||
override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
|
||||
guard let fromViewController = presentingViewController else {
|
||||
return owsFailDebug("Trying to dismiss while not presented.")
|
||||
}
|
||||
|
||||
super.dismiss(animated: flag) { [weak self] in
|
||||
self?.presentToast(
|
||||
text: NSLocalizedString("REQUIRE_PROFILE_NAMES_MEGAPHONE_TOAST",
|
||||
comment: "Toast indicating that a PIN has been created."),
|
||||
fromViewController: fromViewController
|
||||
)
|
||||
completion?()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -562,6 +562,14 @@ NSString *const kProfileView_LastPresentedDate = @"kProfileView_LastPresentedDat
|
||||
.then(^{
|
||||
[modalActivityIndicator dismissWithCompletion:^{
|
||||
[weakSelf updateProfileCompleted];
|
||||
|
||||
// Clear the profile name experience upgrade if the user edits their profile name,
|
||||
// even if they didn't dismiss the reminder directly.
|
||||
[ProfileViewController.databaseStorage
|
||||
asyncWriteWithBlock:^(SDSAnyWriteTransaction *transaction) {
|
||||
[ExperienceUpgradeFinder
|
||||
clearProfileNameReminderWithTransaction:transaction.unwrapGrdbWrite];
|
||||
}];
|
||||
}];
|
||||
})
|
||||
.catch(^(NSError *error) {
|
||||
|
||||
@ -68,6 +68,10 @@ public class ReactionManager: NSObject {
|
||||
}
|
||||
|
||||
SSKEnvironment.shared.messageSenderJobQueue.add(message: outgoingMessage.asPreparer, transaction: transaction)
|
||||
|
||||
// Mark the reactions experience upgrade complete if the user
|
||||
// sends a reaction, even if they didn't dismiss it directly.
|
||||
ExperienceUpgradeFinder.markAsComplete(experienceUpgradeId: .reactions, transaction: transaction.unwrapGrdbWrite)
|
||||
}
|
||||
|
||||
@objc
|
||||
|
||||
@ -8,7 +8,7 @@ import Reachability
|
||||
public enum ExperienceUpgradeId: String, CaseIterable {
|
||||
case introducingPins = "009"
|
||||
case reactions = "010"
|
||||
case requiredProfileNames = "011"
|
||||
case profileNameReminder = "011"
|
||||
|
||||
// Until this flag is true the upgrade won't display to users.
|
||||
var hasLaunched: Bool {
|
||||
@ -19,8 +19,8 @@ public enum ExperienceUpgradeId: String, CaseIterable {
|
||||
SSKEnvironment.shared.reachabilityManager.isReachable
|
||||
case .reactions:
|
||||
return FeatureFlags.reactionSend
|
||||
case .requiredProfileNames:
|
||||
return RemoteConfig.requiredProfileNames
|
||||
case .profileNameReminder:
|
||||
return RemoteConfig.profileNameReminder
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ public enum ExperienceUpgradeId: String, CaseIterable {
|
||||
@objc
|
||||
public class ExperienceUpgradeFinder: NSObject {
|
||||
|
||||
// MARK: - Instance Methods
|
||||
// MARK: -
|
||||
|
||||
public class func next(transaction: GRDBReadTransaction) -> ExperienceUpgrade? {
|
||||
return allActiveExperienceUpgrades(transaction: transaction).first { !$0.isSnoozed }
|
||||
@ -83,6 +83,13 @@ public class ExperienceUpgradeFinder: NSObject {
|
||||
experienceUpgrade.upsertWith(transaction: transaction.asAnyWrite) { $0.lastSnoozedTimestamp = Date().timeIntervalSince1970 }
|
||||
}
|
||||
|
||||
public class func markAsComplete(experienceUpgradeId: ExperienceUpgradeId, transaction: GRDBWriteTransaction) {
|
||||
Logger.info("marking experience upgrade as complete \(experienceUpgradeId)")
|
||||
allActiveExperienceUpgrades(transaction: transaction)
|
||||
.filter { $0.id == experienceUpgradeId }
|
||||
.forEach { markAsComplete(experienceUpgrade: $0, transaction: transaction) }
|
||||
}
|
||||
|
||||
public class func markAsComplete(experienceUpgrade: ExperienceUpgrade, transaction: GRDBWriteTransaction) {
|
||||
Logger.info("marking experience upgrade as complete \(experienceUpgrade.uniqueId)")
|
||||
experienceUpgrade.upsertWith(transaction: transaction.asAnyWrite) { $0.isComplete = true }
|
||||
@ -96,11 +103,20 @@ public class ExperienceUpgradeFinder: NSObject {
|
||||
.forEach { markAsComplete(experienceUpgrade: $0, transaction: transaction) }
|
||||
}
|
||||
|
||||
// MARK: - Experience Specific Helpers
|
||||
|
||||
@objc
|
||||
public class func hasPendingPinExperienceUpgrade(transaction: GRDBReadTransaction) -> Bool {
|
||||
return hasIncomplete(experienceUpgradeId: .introducingPins, transaction: transaction)
|
||||
}
|
||||
|
||||
@objc
|
||||
class func clearProfileNameReminder(transaction: GRDBWriteTransaction) {
|
||||
ExperienceUpgradeFinder.markAsComplete(experienceUpgradeId: .profileNameReminder, transaction: transaction)
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
/// Returns an array of all experience upgrades currently being run that have
|
||||
/// yet to be completed. Sorted by the order of the `ExperienceUpgradeId` enumeration.
|
||||
private class func allActiveExperienceUpgrades(transaction: GRDBReadTransaction) -> [ExperienceUpgrade] {
|
||||
@ -144,11 +160,6 @@ public class ExperienceUpgradeFinder: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
extension OWS2FAManager {
|
||||
|
||||
}
|
||||
|
||||
public extension ExperienceUpgrade {
|
||||
var id: ExperienceUpgradeId! {
|
||||
return ExperienceUpgradeId(rawValue: uniqueId)
|
||||
|
||||
@ -262,7 +262,4 @@ public class FeatureFlags: NSObject {
|
||||
|
||||
@objc
|
||||
public static let useZKGroups = false
|
||||
|
||||
@objc
|
||||
public static let requiredProfileNames = build.includes(.qa)
|
||||
}
|
||||
|
||||
@ -25,10 +25,8 @@ public class RemoteConfig: NSObject {
|
||||
}
|
||||
|
||||
@objc
|
||||
public static var requiredProfileNames: Bool {
|
||||
// Block this off until we're ready to be turning this on for the public.
|
||||
guard FeatureFlags.requiredProfileNames else { return false }
|
||||
return isEnabled("ios.requiredProfileNames")
|
||||
public static var profileNameReminder: Bool {
|
||||
return isEnabled("ios.profileNameReminder")
|
||||
}
|
||||
|
||||
@objc
|
||||
|
||||
Loading…
Reference in New Issue
Block a user