mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Two step verification setup improvements
This commit is contained in:
parent
90ea94d308
commit
791569951f
@ -6,14 +6,8 @@ import RLottieBinding
|
||||
import AppBundle
|
||||
import GZip
|
||||
|
||||
enum ManagedAnimationTrackState {
|
||||
case intro
|
||||
case loop
|
||||
case outro
|
||||
}
|
||||
|
||||
private final class ManagedAnimationState {
|
||||
var item: ManagedAnimationItem
|
||||
let item: ManagedAnimationItem
|
||||
|
||||
private let instance: LottieInstance
|
||||
|
||||
@ -21,33 +15,40 @@ private final class ManagedAnimationState {
|
||||
let fps: Double
|
||||
|
||||
var startTime: Double?
|
||||
var trackState: ManagedAnimationTrackState?
|
||||
var trackingFrameState: (Int, Int)?
|
||||
var frameIndex: Int?
|
||||
|
||||
private let renderContext: DrawingContext
|
||||
|
||||
init?(item: ManagedAnimationItem) {
|
||||
guard let path = getAppBundle().path(forResource: item.name, ofType: "tgs") else {
|
||||
return nil
|
||||
}
|
||||
guard let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
|
||||
return nil
|
||||
}
|
||||
guard let unpackedData = TGGUnzipData(data, 5 * 1024 * 1024) else {
|
||||
return nil
|
||||
}
|
||||
guard let instance = LottieInstance(data: unpackedData, cacheKey: item.name) else {
|
||||
return nil
|
||||
init?(displaySize: CGSize, item: ManagedAnimationItem, current: ManagedAnimationState?) {
|
||||
let resolvedInstance: LottieInstance
|
||||
let renderContext: DrawingContext
|
||||
|
||||
if let current = current {
|
||||
resolvedInstance = current.instance
|
||||
renderContext = current.renderContext
|
||||
} else {
|
||||
guard let path = getAppBundle().path(forResource: item.name, ofType: "tgs") else {
|
||||
return nil
|
||||
}
|
||||
guard let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
|
||||
return nil
|
||||
}
|
||||
guard let unpackedData = TGGUnzipData(data, 5 * 1024 * 1024) else {
|
||||
return nil
|
||||
}
|
||||
guard let instance = LottieInstance(data: unpackedData, cacheKey: item.name) else {
|
||||
return nil
|
||||
}
|
||||
resolvedInstance = instance
|
||||
renderContext = DrawingContext(size: displaySize, scale: UIScreenScale, premultiplied: true, clear: true)
|
||||
}
|
||||
|
||||
self.item = item
|
||||
self.instance = instance
|
||||
self.instance = resolvedInstance
|
||||
self.renderContext = renderContext
|
||||
|
||||
self.frameCount = Int(instance.frameCount)
|
||||
self.fps = Double(instance.frameRate)
|
||||
|
||||
self.renderContext = DrawingContext(size: instance.dimensions, scale: UIScreenScale, premultiplied: true, clear: true)
|
||||
self.frameCount = Int(self.instance.frameCount)
|
||||
self.fps = Double(self.instance.frameRate)
|
||||
}
|
||||
|
||||
func draw() -> UIImage? {
|
||||
@ -56,34 +57,23 @@ private final class ManagedAnimationState {
|
||||
}
|
||||
}
|
||||
|
||||
enum ManagedAnimationActionAtEnd {
|
||||
case pause
|
||||
case advance
|
||||
case loop
|
||||
}
|
||||
|
||||
struct ManagedAnimationTrack: Equatable {
|
||||
let frameRange: Range<Int>
|
||||
struct ManagedAnimationFrameRange: Equatable {
|
||||
var startFrame: Int
|
||||
var endFrame: Int
|
||||
}
|
||||
|
||||
struct ManagedAnimationItem: Equatable {
|
||||
let name: String
|
||||
var intro: ManagedAnimationTrack?
|
||||
var loop: ManagedAnimationTrack?
|
||||
var outro: ManagedAnimationTrack?
|
||||
var frames: ManagedAnimationFrameRange
|
||||
}
|
||||
|
||||
final class ManagedAnimationNode: ASDisplayNode {
|
||||
class ManagedAnimationNode: ASDisplayNode {
|
||||
let intrinsicSize: CGSize
|
||||
|
||||
private let imageNode: ASImageNode
|
||||
private let displayLink: CADisplayLink
|
||||
|
||||
private var items: [ManagedAnimationState] = []
|
||||
|
||||
var currentItemName: String? {
|
||||
return self.items.first?.item.name
|
||||
}
|
||||
private var state: ManagedAnimationState?
|
||||
|
||||
init(size: CGSize) {
|
||||
self.intrinsicSize = size
|
||||
@ -121,136 +111,174 @@ final class ManagedAnimationNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
private func updateAnimation() {
|
||||
guard let item = self.items.first else {
|
||||
guard let state = self.state else {
|
||||
return
|
||||
}
|
||||
let timestamp = CACurrentMediaTime()
|
||||
|
||||
var startTime: Double
|
||||
let maybeTrackState: ManagedAnimationTrackState?
|
||||
if let current = item.startTime {
|
||||
if let current = state.startTime {
|
||||
startTime = current
|
||||
} else {
|
||||
startTime = timestamp
|
||||
item.startTime = startTime
|
||||
}
|
||||
if let current = item.trackState {
|
||||
maybeTrackState = current
|
||||
} else if let _ = item.item.intro {
|
||||
maybeTrackState = .intro
|
||||
} else if let _ = item.item.loop {
|
||||
maybeTrackState = .loop
|
||||
} else if let _ = item.item.outro {
|
||||
maybeTrackState = .outro
|
||||
} else {
|
||||
maybeTrackState = nil
|
||||
}
|
||||
if item.trackState != maybeTrackState {
|
||||
item.trackState = maybeTrackState
|
||||
item.startTime = timestamp
|
||||
startTime = timestamp
|
||||
state.startTime = startTime
|
||||
}
|
||||
|
||||
guard let trackState = maybeTrackState else {
|
||||
self.items.removeFirst()
|
||||
return
|
||||
}
|
||||
let fps = state.fps
|
||||
let frameRange = state.item.frames
|
||||
|
||||
var fps = item.fps
|
||||
let duration: Double = 0.3
|
||||
var t = (timestamp - startTime) / duration
|
||||
t = max(0.0, t)
|
||||
t = min(1.0, t)
|
||||
let frameOffset = Int(Double(frameRange.startFrame) * (1.0 - t) + Double(frameRange.startFrame) * t)
|
||||
let lowerBound = min(frameRange.startFrame, state.frameCount - 1)
|
||||
let upperBound = min(frameRange.endFrame, state.frameCount - 1)
|
||||
let frameIndex = max(lowerBound, min(upperBound, frameOffset))
|
||||
|
||||
let track: ManagedAnimationTrack
|
||||
switch trackState {
|
||||
case .intro:
|
||||
track = item.item.intro!
|
||||
case .loop:
|
||||
track = item.item.loop!
|
||||
if self.items.count > 1 {
|
||||
//fps *= 2.0
|
||||
}
|
||||
case .outro:
|
||||
track = item.item.outro!
|
||||
}
|
||||
|
||||
let frameIndex: Int
|
||||
if let (startFrame, endFrame) = item.trackingFrameState {
|
||||
let duration: Double = 0.3
|
||||
var t = (timestamp - startTime) / duration
|
||||
t = max(0.0, t)
|
||||
t = min(1.0, t)
|
||||
let frameOffset = Int(Double(startFrame) * (1.0 - t) + Double(endFrame) * t)
|
||||
let lowerBound = min(track.frameRange.lowerBound, item.frameCount - 1)
|
||||
let upperBound = min(track.frameRange.upperBound, item.frameCount)
|
||||
frameIndex = max(lowerBound, min(upperBound, frameOffset))
|
||||
} else {
|
||||
let frameOffset = Int((timestamp - startTime) * fps)
|
||||
let lowerBound = min(track.frameRange.lowerBound, item.frameCount - 1)
|
||||
let upperBound = min(track.frameRange.upperBound, item.frameCount)
|
||||
if frameOffset >= upperBound - lowerBound {
|
||||
switch trackState {
|
||||
case .intro:
|
||||
if let _ = item.item.loop {
|
||||
item.trackState = .loop
|
||||
item.startTime = timestamp
|
||||
return
|
||||
} else if let _ = item.item.outro {
|
||||
item.trackState = .outro
|
||||
item.startTime = timestamp
|
||||
return
|
||||
} else {
|
||||
self.items.removeFirst()
|
||||
return
|
||||
}
|
||||
case .loop:
|
||||
if self.items.count > 1 {
|
||||
if let _ = item.item.outro {
|
||||
item.trackState = .outro
|
||||
item.startTime = timestamp
|
||||
} else {
|
||||
self.items.removeFirst()
|
||||
}
|
||||
return
|
||||
} else {
|
||||
item.startTime = timestamp
|
||||
frameIndex = lowerBound
|
||||
}
|
||||
case .outro:
|
||||
self.items.removeFirst()
|
||||
return
|
||||
}
|
||||
} else {
|
||||
frameIndex = lowerBound + frameOffset % (upperBound - lowerBound)
|
||||
}
|
||||
}
|
||||
|
||||
if item.frameIndex != frameIndex {
|
||||
item.frameIndex = frameIndex
|
||||
if let image = item.draw() {
|
||||
if state.frameIndex != frameIndex {
|
||||
state.frameIndex = frameIndex
|
||||
if let image = state.draw() {
|
||||
self.imageNode.image = image
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func switchTo(_ item: ManagedAnimationItem, noOutro: Bool = false) {
|
||||
if let state = ManagedAnimationState(item: item) {
|
||||
if let last = self.items.last {
|
||||
if last.item.name == item.name {
|
||||
return
|
||||
}
|
||||
}
|
||||
if let first = self.items.first {
|
||||
if noOutro {
|
||||
first.item.outro = nil
|
||||
}
|
||||
}
|
||||
self.items.append(state)
|
||||
self.updateAnimation()
|
||||
func trackTo(item: ManagedAnimationItem, frameIndex: Int) {
|
||||
if let state = self.state, state.item.name == item.name {
|
||||
self.state = ManagedAnimationState(displaySize: self.intrinsicSize, item: item, current: state)
|
||||
} else {
|
||||
self.state = ManagedAnimationState(displaySize: self.intrinsicSize, item: item, current: nil)
|
||||
}
|
||||
self.updateAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
enum ManagedMonkeyAnimationState: Equatable {
|
||||
case idle
|
||||
case eyesClosed
|
||||
case peeking
|
||||
case tracking(CGFloat)
|
||||
}
|
||||
|
||||
/*private let animationIdle = ManagedAnimationItem(name: "TwoFactorSetupMonkeyIdle",
|
||||
intro: nil,
|
||||
loop: ManagedAnimationTrack(frameRange: 0 ..< 1),
|
||||
outro: nil
|
||||
)
|
||||
|
||||
private let animationIdle = ManagedAnimationItem(name: "TwoFactorSetupMonkeyIdle",
|
||||
intro: nil,
|
||||
loop: ManagedAnimationTrack(frameRange: 0 ..< 1),
|
||||
outro: nil
|
||||
)
|
||||
|
||||
private let animationTracking = ManagedAnimationItem(name: "TwoFactorSetupMonkeyTracking",
|
||||
intro: nil,
|
||||
loop: ManagedAnimationTrack(frameRange: 0 ..< Int.max),
|
||||
outro: nil
|
||||
)
|
||||
|
||||
private let animationHide = ManagedAnimationItem(name: "TwoFactorSetupMonkeyClose",
|
||||
intro: ManagedAnimationTrack(frameRange: 0 ..< 41),
|
||||
loop: ManagedAnimationTrack(frameRange: 40 ..< 41),
|
||||
outro: ManagedAnimationTrack(frameRange: 60 ..< 99)
|
||||
)
|
||||
|
||||
private let animationHideNoOutro = ManagedAnimationItem(name: "TwoFactorSetupMonkeyClose",
|
||||
intro: ManagedAnimationTrack(frameRange: 0 ..< 41),
|
||||
loop: ManagedAnimationTrack(frameRange: 40 ..< 41),
|
||||
outro: nil
|
||||
)
|
||||
|
||||
private let animationHideNoIntro = ManagedAnimationItem(name: "TwoFactorSetupMonkeyClose",
|
||||
intro: nil,
|
||||
loop: ManagedAnimationTrack(frameRange: 40 ..< 41),
|
||||
outro: ManagedAnimationTrack(frameRange: 60 ..< 99)
|
||||
)
|
||||
|
||||
private let animationHideOutro = ManagedAnimationItem(name: "TwoFactorSetupMonkeyClose",
|
||||
intro: nil,
|
||||
loop: nil,
|
||||
outro: ManagedAnimationTrack(frameRange: 60 ..< 99)
|
||||
)
|
||||
|
||||
private let animationPeek = ManagedAnimationItem(name: "TwoFactorSetupMonkeyPeek",
|
||||
intro: ManagedAnimationTrack(frameRange: 0 ..< 14),
|
||||
loop: ManagedAnimationTrack(frameRange: 13 ..< 14),
|
||||
outro: ManagedAnimationTrack(frameRange: 14 ..< 34)
|
||||
)
|
||||
|
||||
private let animationMail = ManagedAnimationItem(name: "TwoFactorSetupMail",
|
||||
intro: ManagedAnimationTrack(frameRange: 0 ..< Int.max),
|
||||
loop: ManagedAnimationTrack(frameRange: Int.max - 1 ..< Int.max),
|
||||
outro: nil
|
||||
)
|
||||
|
||||
private let animationHint = ManagedAnimationItem(name: "TwoFactorSetupHint",
|
||||
intro: ManagedAnimationTrack(frameRange: 0 ..< Int.max),
|
||||
loop: ManagedAnimationTrack(frameRange: Int.max - 1 ..< Int.max),
|
||||
outro: nil
|
||||
)*/
|
||||
|
||||
final class ManagedMonkeyAnimationNode: ManagedAnimationNode {
|
||||
private var state: ManagedMonkeyAnimationState = .idle
|
||||
|
||||
init() {
|
||||
super.init(size: CGSize(width: 136.0, height: 136.0))
|
||||
|
||||
self.trackTo(item: ManagedAnimationItem(name: "TwoFactorSetupMonkeyIdle", frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 0)), frameIndex: 0)
|
||||
}
|
||||
|
||||
func trackTo(frameIndex: Int) {
|
||||
if let first = self.items.first {
|
||||
first.startTime = CACurrentMediaTime()
|
||||
first.trackingFrameState = (first.frameIndex ?? 0, frameIndex)
|
||||
self.updateAnimation()
|
||||
func setState(_ state: ManagedMonkeyAnimationState) {
|
||||
let previousState = self.state
|
||||
self.state = state
|
||||
|
||||
switch previousState {
|
||||
case .idle:
|
||||
switch state {
|
||||
case .idle:
|
||||
break
|
||||
case .eyesClosed:
|
||||
break
|
||||
case .peeking:
|
||||
break
|
||||
case let .tracking(value):
|
||||
break
|
||||
}
|
||||
case .eyesClosed:
|
||||
switch state {
|
||||
case .idle:
|
||||
break
|
||||
case .eyesClosed:
|
||||
break
|
||||
case .peeking:
|
||||
break
|
||||
case let .tracking(value):
|
||||
break
|
||||
}
|
||||
case .peeking:
|
||||
switch state {
|
||||
case .idle:
|
||||
break
|
||||
case .eyesClosed:
|
||||
break
|
||||
case .peeking:
|
||||
break
|
||||
case let .tracking(value):
|
||||
break
|
||||
}
|
||||
case let .tracking(previousValue):
|
||||
switch state {
|
||||
case .idle:
|
||||
break
|
||||
case .eyesClosed:
|
||||
break
|
||||
case .peeking:
|
||||
break
|
||||
case let .tracking(value):
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,76 +10,28 @@ import AccountContext
|
||||
import TelegramPresentationData
|
||||
import PresentationDataUtils
|
||||
import TelegramCore
|
||||
import AnimatedStickerNode
|
||||
|
||||
public enum TwoFactorDataInputMode {
|
||||
case password
|
||||
case emailAddress(password: String)
|
||||
case emailConfirmation(password: String?, emailPattern: String)
|
||||
case emailAddress(password: String, hint: String)
|
||||
case updateEmailAddress(password: String)
|
||||
case emailConfirmation(passwordAndHint: (String, String)?, emailPattern: String, codeLength: Int?)
|
||||
case passwordHint(password: String)
|
||||
}
|
||||
|
||||
private let animationIdle = ManagedAnimationItem(name: "TwoFactorSetupMonkeyIdle",
|
||||
intro: nil,
|
||||
loop: ManagedAnimationTrack(frameRange: 0 ..< 1),
|
||||
outro: nil
|
||||
)
|
||||
|
||||
private let animationTracking = ManagedAnimationItem(name: "TwoFactorSetupMonkeyTracking",
|
||||
intro: nil,
|
||||
loop: ManagedAnimationTrack(frameRange: 0 ..< Int.max),
|
||||
outro: nil
|
||||
)
|
||||
|
||||
private let animationHide = ManagedAnimationItem(name: "TwoFactorSetupMonkeyClose",
|
||||
intro: ManagedAnimationTrack(frameRange: 0 ..< 41),
|
||||
loop: ManagedAnimationTrack(frameRange: 40 ..< 41),
|
||||
outro: ManagedAnimationTrack(frameRange: 60 ..< 99)
|
||||
)
|
||||
|
||||
private let animationHideNoOutro = ManagedAnimationItem(name: "TwoFactorSetupMonkeyClose",
|
||||
intro: ManagedAnimationTrack(frameRange: 0 ..< 41),
|
||||
loop: ManagedAnimationTrack(frameRange: 40 ..< 41),
|
||||
outro: nil
|
||||
)
|
||||
|
||||
private let animationHideNoIntro = ManagedAnimationItem(name: "TwoFactorSetupMonkeyClose",
|
||||
intro: nil,
|
||||
loop: ManagedAnimationTrack(frameRange: 40 ..< 41),
|
||||
outro: ManagedAnimationTrack(frameRange: 60 ..< 99)
|
||||
)
|
||||
|
||||
private let animationHideOutro = ManagedAnimationItem(name: "TwoFactorSetupMonkeyClose",
|
||||
intro: nil,
|
||||
loop: nil,
|
||||
outro: ManagedAnimationTrack(frameRange: 60 ..< 99)
|
||||
)
|
||||
|
||||
private let animationPeek = ManagedAnimationItem(name: "TwoFactorSetupMonkeyPeek",
|
||||
intro: ManagedAnimationTrack(frameRange: 0 ..< 14),
|
||||
loop: ManagedAnimationTrack(frameRange: 13 ..< 14),
|
||||
outro: ManagedAnimationTrack(frameRange: 14 ..< 34)
|
||||
)
|
||||
|
||||
private let animationMail = ManagedAnimationItem(name: "TwoFactorSetupMail",
|
||||
intro: ManagedAnimationTrack(frameRange: 0 ..< Int.max),
|
||||
loop: ManagedAnimationTrack(frameRange: Int.max - 1 ..< Int.max),
|
||||
outro: nil
|
||||
)
|
||||
|
||||
private let animationHint = ManagedAnimationItem(name: "TwoFactorSetupHint",
|
||||
intro: ManagedAnimationTrack(frameRange: 0 ..< Int.max),
|
||||
loop: ManagedAnimationTrack(frameRange: Int.max - 1 ..< Int.max),
|
||||
outro: nil
|
||||
)
|
||||
|
||||
public final class TwoFactorDataInputScreen: ViewController {
|
||||
private let context: AccountContext
|
||||
private var presentationData: PresentationData
|
||||
private let mode: TwoFactorDataInputMode
|
||||
private let stateUpdated: (SetupTwoStepVerificationStateUpdate) -> Void
|
||||
|
||||
public init(context: AccountContext, mode: TwoFactorDataInputMode) {
|
||||
public init(context: AccountContext, mode: TwoFactorDataInputMode, stateUpdated: @escaping (SetupTwoStepVerificationStateUpdate) -> Void) {
|
||||
self.context = context
|
||||
self.mode = mode
|
||||
self.stateUpdated = stateUpdated
|
||||
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
@ -131,14 +83,82 @@ public final class TwoFactorDataInputScreen: ViewController {
|
||||
if controller is TwoFactorAuthSplashScreen {
|
||||
return false
|
||||
}
|
||||
if controller is TwoFactorDataInputScreen {
|
||||
if controller is TwoFactorDataInputScreen && controller !== strongSelf {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
controllers.append(TwoFactorDataInputScreen(context: strongSelf.context, mode: .passwordHint(password: values[0])))
|
||||
controllers.append(TwoFactorDataInputScreen(context: strongSelf.context, mode: .passwordHint(password: values[0]), stateUpdated: strongSelf.stateUpdated))
|
||||
navigationController.setViewControllers(controllers, animated: true)
|
||||
case let .emailAddress(password):
|
||||
case let .emailAddress(password, hint):
|
||||
guard let text = (strongSelf.displayNode as! TwoFactorDataInputScreenNode).inputText.first, !text.isEmpty else {
|
||||
return
|
||||
}
|
||||
let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: nil))
|
||||
strongSelf.present(statusController, in: .window(.root))
|
||||
|
||||
let _ = (updateTwoStepVerificationPassword(network: strongSelf.context.account.network, currentPassword: "", updatedPassword: .password(password: password, hint: hint, email: text))
|
||||
|> deliverOnMainQueue).start(next: { [weak statusController] result in
|
||||
statusController?.dismiss()
|
||||
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
switch result {
|
||||
case .none:
|
||||
break
|
||||
case let .password(_, pendingEmail):
|
||||
if let pendingEmail = pendingEmail {
|
||||
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
||||
return
|
||||
}
|
||||
var controllers = navigationController.viewControllers.filter { controller in
|
||||
if controller is TwoFactorAuthSplashScreen {
|
||||
return false
|
||||
}
|
||||
if controller is TwoFactorDataInputScreen {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
controllers.append(TwoFactorDataInputScreen(context: strongSelf.context, mode: .emailConfirmation(passwordAndHint: (password, hint), emailPattern: text, codeLength: pendingEmail.codeLength.flatMap(Int.init)), stateUpdated: strongSelf.stateUpdated))
|
||||
navigationController.setViewControllers(controllers, animated: true)
|
||||
} else {
|
||||
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
||||
return
|
||||
}
|
||||
var controllers = navigationController.viewControllers.filter { controller in
|
||||
if controller is TwoFactorAuthSplashScreen {
|
||||
return false
|
||||
}
|
||||
if controller is TwoFactorDataInputScreen {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
controllers.append(TwoFactorAuthSplashScreen(context: strongSelf.context, mode: .done))
|
||||
navigationController.setViewControllers(controllers, animated: true)
|
||||
}
|
||||
}
|
||||
}, error: { [weak statusController] error in
|
||||
statusController?.dismiss()
|
||||
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
let presentationData = strongSelf.presentationData
|
||||
let alertText: String
|
||||
switch error {
|
||||
case .generic:
|
||||
alertText = presentationData.strings.Login_UnknownError
|
||||
case .invalidEmail:
|
||||
alertText = presentationData.strings.TwoStepAuth_EmailInvalid
|
||||
}
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: alertText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
})
|
||||
case let .updateEmailAddress(password):
|
||||
guard let text = (strongSelf.displayNode as! TwoFactorDataInputScreenNode).inputText.first, !text.isEmpty else {
|
||||
return
|
||||
}
|
||||
@ -156,7 +176,7 @@ public final class TwoFactorDataInputScreen: ViewController {
|
||||
switch result {
|
||||
case .none:
|
||||
break
|
||||
case let .password(password, pendingEmail):
|
||||
case let .password(_, pendingEmail):
|
||||
if let pendingEmail = pendingEmail {
|
||||
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
||||
return
|
||||
@ -170,7 +190,7 @@ public final class TwoFactorDataInputScreen: ViewController {
|
||||
}
|
||||
return true
|
||||
}
|
||||
controllers.append(TwoFactorDataInputScreen(context: strongSelf.context, mode: .emailConfirmation(password: password, emailPattern: text)))
|
||||
controllers.append(TwoFactorDataInputScreen(context: strongSelf.context, mode: .emailConfirmation(passwordAndHint: (password, ""), emailPattern: text, codeLength: pendingEmail.codeLength.flatMap(Int.init)), stateUpdated: strongSelf.stateUpdated))
|
||||
navigationController.setViewControllers(controllers, animated: true)
|
||||
} else {
|
||||
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
||||
@ -263,38 +283,71 @@ public final class TwoFactorDataInputScreen: ViewController {
|
||||
return
|
||||
}
|
||||
|
||||
strongSelf.setPassword(password: password, hint: value)
|
||||
strongSelf.push(TwoFactorDataInputScreen(context: strongSelf.context, mode: .emailAddress(password: password, hint: value), stateUpdated: strongSelf.stateUpdated))
|
||||
}
|
||||
}, skipAction: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
switch strongSelf.mode {
|
||||
case .emailAddress:
|
||||
case let .emailAddress(password, hint):
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: strongSelf.presentationData.strings.TwoFactorSetup_Email_SkipConfirmationTitle, text: strongSelf.presentationData.strings.TwoFactorSetup_Email_SkipConfirmationText, actions: [
|
||||
TextAlertAction(type: .destructiveAction, title: strongSelf.presentationData.strings.TwoFactorSetup_Email_SkipConfirmationSkip, action: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
||||
return
|
||||
}
|
||||
var controllers = navigationController.viewControllers.filter { controller in
|
||||
if controller is TwoFactorAuthSplashScreen {
|
||||
return false
|
||||
let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: nil))
|
||||
strongSelf.present(statusController, in: .window(.root))
|
||||
|
||||
let _ = (updateTwoStepVerificationPassword(network: strongSelf.context.account.network, currentPassword: "", updatedPassword: .password(password: password, hint: hint, email: nil))
|
||||
|> deliverOnMainQueue).start(next: { [weak statusController] result in
|
||||
statusController?.dismiss()
|
||||
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if controller is TwoFactorDataInputScreen {
|
||||
return false
|
||||
|
||||
switch result {
|
||||
case .none:
|
||||
break
|
||||
case .password:
|
||||
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
||||
return
|
||||
}
|
||||
var controllers = navigationController.viewControllers.filter { controller in
|
||||
if controller is TwoFactorAuthSplashScreen {
|
||||
return false
|
||||
}
|
||||
if controller is TwoFactorDataInputScreen {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
controllers.append(TwoFactorAuthSplashScreen(context: strongSelf.context, mode: .done))
|
||||
navigationController.setViewControllers(controllers, animated: true)
|
||||
}
|
||||
return true
|
||||
}
|
||||
controllers.append(TwoFactorAuthSplashScreen(context: strongSelf.context, mode: .done))
|
||||
navigationController.setViewControllers(controllers, animated: true)
|
||||
}, error: { [weak statusController] error in
|
||||
statusController?.dismiss()
|
||||
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
let presentationData = strongSelf.presentationData
|
||||
let alertText: String
|
||||
switch error {
|
||||
case .generic:
|
||||
alertText = presentationData.strings.Login_UnknownError
|
||||
case .invalidEmail:
|
||||
alertText = presentationData.strings.TwoStepAuth_EmailInvalid
|
||||
}
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: alertText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
})
|
||||
}),
|
||||
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})
|
||||
]), in: .window(.root))
|
||||
case let .passwordHint(password):
|
||||
strongSelf.setPassword(password: password, hint: "")
|
||||
strongSelf.push(TwoFactorDataInputScreen(context: strongSelf.context, mode: .emailAddress(password: password, hint: ""), stateUpdated: strongSelf.stateUpdated))
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -303,8 +356,8 @@ public final class TwoFactorDataInputScreen: ViewController {
|
||||
return
|
||||
}
|
||||
switch strongSelf.mode {
|
||||
case let .emailConfirmation(password, _):
|
||||
if let password = password {
|
||||
case let .emailConfirmation(passwordAndHint, _, _):
|
||||
if let (password, hint) = passwordAndHint {
|
||||
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
||||
return
|
||||
}
|
||||
@ -317,7 +370,7 @@ public final class TwoFactorDataInputScreen: ViewController {
|
||||
}
|
||||
return true
|
||||
}
|
||||
controllers.append(TwoFactorDataInputScreen(context: strongSelf.context, mode: .emailAddress(password: password)))
|
||||
controllers.append(TwoFactorDataInputScreen(context: strongSelf.context, mode: .emailAddress(password: password, hint: hint), stateUpdated: strongSelf.stateUpdated))
|
||||
navigationController.setViewControllers(controllers, animated: true)
|
||||
} else {
|
||||
}
|
||||
@ -356,41 +409,6 @@ public final class TwoFactorDataInputScreen: ViewController {
|
||||
self.displayNodeDidLoad()
|
||||
}
|
||||
|
||||
private func setPassword(password: String, hint: String) {
|
||||
let statusController = OverlayStatusController(theme: self.presentationData.theme, type: .loading(cancelled: nil))
|
||||
self.present(statusController, in: .window(.root))
|
||||
|
||||
let _ = (updateTwoStepVerificationPassword(network: self.context.account.network, currentPassword: nil, updatedPassword: .password(password: password, hint: hint, email: nil))
|
||||
|> deliverOnMainQueue).start(next: { [weak self, weak statusController] _ in
|
||||
statusController?.dismiss()
|
||||
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
||||
return
|
||||
}
|
||||
var controllers = navigationController.viewControllers.filter { controller in
|
||||
if controller is TwoFactorAuthSplashScreen {
|
||||
return false
|
||||
}
|
||||
if controller is TwoFactorDataInputScreen {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
controllers.append(TwoFactorDataInputScreen(context: strongSelf.context, mode: .emailAddress(password: password)))
|
||||
navigationController.setViewControllers(controllers, animated: true)
|
||||
}, error: { [weak self, weak statusController] _ in
|
||||
statusController?.dismiss()
|
||||
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
super.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
@ -612,7 +630,8 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
||||
private let navigationBackgroundNode: ASDisplayNode
|
||||
private let navigationSeparatorNode: ASDisplayNode
|
||||
private let scrollNode: ASScrollNode
|
||||
private let animationNode: ManagedAnimationNode
|
||||
private var animatedStickerNode: AnimatedStickerNode?
|
||||
private var monkeyNode: ManagedMonkeyAnimationNode?
|
||||
private let titleNode: ImmediateTextNode
|
||||
private let textNode: ImmediateTextNode
|
||||
private let skipActionTitleNode: ImmediateTextNode
|
||||
@ -647,7 +666,24 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
||||
self.scrollNode = ASScrollNode()
|
||||
self.scrollNode.canCancelAllTouchesInViews = true
|
||||
|
||||
self.animationNode = ManagedAnimationNode(size: CGSize(width: 136.0, height: 136.0))
|
||||
switch mode {
|
||||
case .password, .emailAddress, .updateEmailAddress:
|
||||
self.monkeyNode = ManagedMonkeyAnimationNode()
|
||||
case .emailConfirmation:
|
||||
if let path = getAppBundle().path(forResource: "TwoFactorSetupMail", ofType: "tgs") {
|
||||
let animatedStickerNode = AnimatedStickerNode()
|
||||
animatedStickerNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 272, height: 272, playbackMode: .once, mode: .direct)
|
||||
animatedStickerNode.visibility = true
|
||||
self.animatedStickerNode = animatedStickerNode
|
||||
}
|
||||
case .passwordHint:
|
||||
if let path = getAppBundle().path(forResource: "TwoFactorSetupHint", ofType: "tgs") {
|
||||
let animatedStickerNode = AnimatedStickerNode()
|
||||
animatedStickerNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 272, height: 272, playbackMode: .once, mode: .direct)
|
||||
animatedStickerNode.visibility = true
|
||||
self.animatedStickerNode = animatedStickerNode
|
||||
}
|
||||
}
|
||||
|
||||
let title: String
|
||||
let text: NSAttributedString
|
||||
@ -664,8 +700,6 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
||||
|
||||
switch mode {
|
||||
case .password:
|
||||
self.animationNode.switchTo(animationIdle)
|
||||
|
||||
title = presentationData.strings.TwoFactorSetup_Password_Title
|
||||
text = NSAttributedString(string: "", font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
|
||||
buttonText = presentationData.strings.TwoFactorSetup_Password_Action
|
||||
@ -692,9 +726,7 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
||||
toggleTextHidden?(node)
|
||||
})
|
||||
]
|
||||
case .emailAddress:
|
||||
self.animationNode.switchTo(animationTracking)
|
||||
|
||||
case .emailAddress, .updateEmailAddress:
|
||||
title = presentationData.strings.TwoFactorSetup_Email_Title
|
||||
text = NSAttributedString(string: presentationData.strings.TwoFactorSetup_Email_Text, font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
|
||||
buttonText = presentationData.strings.TwoFactorSetup_Email_Action
|
||||
@ -712,9 +744,7 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
||||
toggleTextHidden?(node)
|
||||
}),
|
||||
]
|
||||
case let .emailConfirmation(_, emailPattern):
|
||||
self.animationNode.switchTo(animationMail)
|
||||
|
||||
case let .emailConfirmation(_, emailPattern, _):
|
||||
title = presentationData.strings.TwoFactorSetup_EmailVerification_Title
|
||||
let (rawText, ranges) = presentationData.strings.TwoFactorSetup_EmailVerification_Text(emailPattern)
|
||||
|
||||
@ -742,8 +772,6 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
||||
}),
|
||||
]
|
||||
case .passwordHint:
|
||||
self.animationNode.switchTo(animationHint)
|
||||
|
||||
title = presentationData.strings.TwoFactorSetup_Hint_Title
|
||||
|
||||
text = NSAttributedString(string: presentationData.strings.TwoFactorSetup_Hint_Text, font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
|
||||
@ -812,7 +840,8 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
||||
|
||||
self.addSubnode(self.scrollNode)
|
||||
|
||||
self.scrollNode.addSubnode(self.animationNode)
|
||||
self.animatedStickerNode.flatMap(self.scrollNode.addSubnode)
|
||||
self.monkeyNode.flatMap(self.scrollNode.addSubnode)
|
||||
self.scrollNode.addSubnode(self.titleNode)
|
||||
self.scrollNode.addSubnode(self.textNode)
|
||||
self.scrollNode.addSubnode(self.skipActionTitleNode)
|
||||
@ -880,7 +909,13 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
if let index = strongSelf.inputNodes.index(where: { $0 === node }) {
|
||||
if index == strongSelf.inputNodes.count - 1 {
|
||||
strongSelf.action()
|
||||
} else if strongSelf.buttonNode.isUserInteractionEnabled {
|
||||
strongSelf.inputNodes[index + 1].focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
focused = { [weak self] node in
|
||||
DispatchQueue.main.async {
|
||||
@ -895,7 +930,7 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
||||
return
|
||||
}
|
||||
let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty })
|
||||
switch strongSelf.mode {
|
||||
/*switch strongSelf.mode {
|
||||
case .password:
|
||||
if !hasText {
|
||||
if strongSelf.animationNode.currentItemName == animationPeek.name {
|
||||
@ -942,25 +977,30 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}*/
|
||||
}
|
||||
updated = { [weak self] _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
switch strongSelf.mode {
|
||||
case .emailAddress:
|
||||
case .emailAddress, .updateEmailAddress:
|
||||
let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty })
|
||||
strongSelf.buttonNode.isHidden = !hasText
|
||||
strongSelf.skipActionTitleNode.isHidden = hasText
|
||||
strongSelf.skipActionButtonNode.isHidden = hasText
|
||||
case .emailConfirmation:
|
||||
let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty })
|
||||
case let .emailConfirmation(_, _, codeLength):
|
||||
let text = strongSelf.inputNodes[0].text
|
||||
let hasText = !text.isEmpty
|
||||
strongSelf.buttonNode.isHidden = !hasText
|
||||
strongSelf.changeEmailActionTitleNode.isHidden = hasText
|
||||
strongSelf.changeEmailActionButtonNode.isHidden = hasText
|
||||
strongSelf.resendCodeActionTitleNode.isHidden = hasText
|
||||
strongSelf.resendCodeActionButtonNode.isHidden = hasText
|
||||
|
||||
if let codeLength = codeLength, text.count == codeLength {
|
||||
action()
|
||||
}
|
||||
case .passwordHint:
|
||||
let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty })
|
||||
strongSelf.buttonNode.isHidden = !hasText
|
||||
@ -1041,7 +1081,14 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
||||
|
||||
transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: contentAreaSize))
|
||||
|
||||
let iconSize: CGSize = self.animationNode.intrinsicSize
|
||||
let iconSize: CGSize
|
||||
if let animatedStickerNode = self.animatedStickerNode {
|
||||
iconSize = CGSize(width: 136.0, height: 136.0)
|
||||
} else if let monkeyNode = self.monkeyNode {
|
||||
iconSize = monkeyNode.intrinsicSize
|
||||
} else {
|
||||
iconSize = CGSize(width: 100.0, height: 100.0)
|
||||
}
|
||||
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: contentAreaSize.width - sideInset * 2.0, height: contentAreaSize.height))
|
||||
let textSize = self.textNode.updateLayout(CGSize(width: contentAreaSize.width - sideInset * 2.0, height: contentAreaSize.height))
|
||||
@ -1070,7 +1117,11 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
||||
let contentVerticalOrigin = max(layout.statusBarHeight ?? 0.0, floor((areaHeight - calculatedContentHeight) / 2.0))
|
||||
|
||||
let iconFrame = CGRect(origin: CGPoint(x: floor((contentAreaSize.width - iconSize.width) / 2.0), y: contentVerticalOrigin), size: iconSize)
|
||||
transition.updateFrame(node: self.animationNode, frame: iconFrame)
|
||||
if let animatedStickerNode = self.animatedStickerNode {
|
||||
transition.updateFrame(node: animatedStickerNode, frame: iconFrame)
|
||||
} else if let monkeyNode = self.monkeyNode {
|
||||
transition.updateFrame(node: monkeyNode, frame: iconFrame)
|
||||
}
|
||||
let titleFrame = CGRect(origin: CGPoint(x: floor((contentAreaSize.width - titleSize.width) / 2.0), y: iconFrame.maxY + iconSpacing), size: titleSize)
|
||||
transition.updateFrameAdditive(node: self.titleNode, frame: titleFrame)
|
||||
let textFrame: CGRect
|
||||
|
@ -54,7 +54,8 @@ public final class TwoFactorAuthSplashScreen: ViewController {
|
||||
}
|
||||
switch strongSelf.mode {
|
||||
case .intro:
|
||||
strongSelf.push(TwoFactorDataInputScreen(context: strongSelf.context, mode: .password))
|
||||
strongSelf.push(TwoFactorDataInputScreen(context: strongSelf.context, mode: .password, stateUpdated: { _ in
|
||||
}))
|
||||
case .done:
|
||||
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
||||
return
|
||||
|
@ -268,6 +268,7 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
|
||||
|
||||
var replaceControllerImpl: ((ViewController, Bool) -> Void)?
|
||||
var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)?
|
||||
var dismissImpl: (() -> Void)?
|
||||
|
||||
let actionsDisposable = DisposableSet()
|
||||
|
||||
@ -629,7 +630,8 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
|
||||
state.checking = false
|
||||
return state
|
||||
}
|
||||
dataPromise.set(.single(TwoStepVerificationUnlockSettingsControllerData.access(configuration: .notSet(pendingEmail: nil))))
|
||||
//dataPromise.set(.single(TwoStepVerificationUnlockSettingsControllerData.access(configuration: .notSet(pendingEmail: nil))))
|
||||
dismissImpl?()
|
||||
}))
|
||||
}
|
||||
})]), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
@ -642,33 +644,35 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { data in
|
||||
switch data {
|
||||
case .access:
|
||||
break
|
||||
case let .manage(password, emailSet, _, hasSecureValues):
|
||||
let controller = SetupTwoStepVerificationController(context: context, initialState: .addEmail(hadRecoveryEmail: emailSet, hasSecureValues: hasSecureValues, password: password), stateUpdated: { update, shouldDismiss, controller in
|
||||
switch update {
|
||||
case .noPassword:
|
||||
assertionFailure()
|
||||
break
|
||||
case let .awaitingEmailConfirmation(password, pattern, codeLength):
|
||||
let data: TwoStepVerificationUnlockSettingsControllerData = .manage(password: password, emailSet: emailSet, pendingEmail: TwoStepVerificationPendingEmail(pattern: pattern, codeLength: codeLength), hasSecureValues: hasSecureValues)
|
||||
case .access:
|
||||
break
|
||||
case let .manage(password, emailSet, _, hasSecureValues):
|
||||
//let controller = TwoFactorDataInputScreen(context: context, mode: .updateEmailAddress(password: password))
|
||||
|
||||
let controller = SetupTwoStepVerificationController(context: context, initialState: .addEmail(hadRecoveryEmail: emailSet, hasSecureValues: hasSecureValues, password: password), stateUpdated: { update, shouldDismiss, controller in
|
||||
switch update {
|
||||
case .noPassword:
|
||||
assertionFailure()
|
||||
break
|
||||
case let .awaitingEmailConfirmation(password, pattern, codeLength):
|
||||
let data: TwoStepVerificationUnlockSettingsControllerData = .manage(password: password, emailSet: emailSet, pendingEmail: TwoStepVerificationPendingEmail(pattern: pattern, codeLength: codeLength), hasSecureValues: hasSecureValues)
|
||||
dataPromise.set(.single(data))
|
||||
case let .passwordSet(password, hasRecoveryEmail, hasSecureValues):
|
||||
if let password = password {
|
||||
let data: TwoStepVerificationUnlockSettingsControllerData = .manage(password: password, emailSet: hasRecoveryEmail, pendingEmail: nil, hasSecureValues: hasSecureValues)
|
||||
dataPromise.set(.single(data))
|
||||
case let .passwordSet(password, hasRecoveryEmail, hasSecureValues):
|
||||
if let password = password {
|
||||
let data: TwoStepVerificationUnlockSettingsControllerData = .manage(password: password, emailSet: hasRecoveryEmail, pendingEmail: nil, hasSecureValues: hasSecureValues)
|
||||
dataPromise.set(.single(data))
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
presentControllerImpl?(OverlayStatusController(theme: presentationData.theme, type: .genericSuccess(emailSet ? presentationData.strings.TwoStepAuth_EmailChangeSuccess : presentationData.strings.TwoStepAuth_EmailAddSuccess, false)), nil)
|
||||
} else {
|
||||
dataPromise.set(.single(.access(configuration: nil))
|
||||
|> then(twoStepVerificationConfiguration(account: context.account) |> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: password)) }))
|
||||
}
|
||||
}
|
||||
if shouldDismiss {
|
||||
controller.dismiss()
|
||||
}
|
||||
})
|
||||
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
presentControllerImpl?(OverlayStatusController(theme: presentationData.theme, type: .genericSuccess(emailSet ? presentationData.strings.TwoStepAuth_EmailChangeSuccess : presentationData.strings.TwoStepAuth_EmailAddSuccess, false)), nil)
|
||||
} else {
|
||||
dataPromise.set(.single(.access(configuration: nil))
|
||||
|> then(twoStepVerificationConfiguration(account: context.account) |> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: password)) }))
|
||||
}
|
||||
}
|
||||
if shouldDismiss {
|
||||
controller.dismiss()
|
||||
}
|
||||
})
|
||||
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
}
|
||||
}))
|
||||
}, openResetPendingEmail: {
|
||||
@ -822,6 +826,9 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
|
||||
controller.present(c, in: .window(.root), with: p)
|
||||
}
|
||||
}
|
||||
dismissImpl = { [weak controller] in
|
||||
controller?.dismiss()
|
||||
}
|
||||
initialFocusImpl = { [weak controller] in
|
||||
guard let controller = controller, controller.didAppearOnce else {
|
||||
return
|
||||
|
Loading…
x
Reference in New Issue
Block a user