mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 09:20:08 +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 AppBundle
|
||||||
import GZip
|
import GZip
|
||||||
|
|
||||||
enum ManagedAnimationTrackState {
|
|
||||||
case intro
|
|
||||||
case loop
|
|
||||||
case outro
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class ManagedAnimationState {
|
private final class ManagedAnimationState {
|
||||||
var item: ManagedAnimationItem
|
let item: ManagedAnimationItem
|
||||||
|
|
||||||
private let instance: LottieInstance
|
private let instance: LottieInstance
|
||||||
|
|
||||||
@ -21,13 +15,18 @@ private final class ManagedAnimationState {
|
|||||||
let fps: Double
|
let fps: Double
|
||||||
|
|
||||||
var startTime: Double?
|
var startTime: Double?
|
||||||
var trackState: ManagedAnimationTrackState?
|
|
||||||
var trackingFrameState: (Int, Int)?
|
|
||||||
var frameIndex: Int?
|
var frameIndex: Int?
|
||||||
|
|
||||||
private let renderContext: DrawingContext
|
private let renderContext: DrawingContext
|
||||||
|
|
||||||
init?(item: ManagedAnimationItem) {
|
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 {
|
guard let path = getAppBundle().path(forResource: item.name, ofType: "tgs") else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -40,14 +39,16 @@ private final class ManagedAnimationState {
|
|||||||
guard let instance = LottieInstance(data: unpackedData, cacheKey: item.name) else {
|
guard let instance = LottieInstance(data: unpackedData, cacheKey: item.name) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
resolvedInstance = instance
|
||||||
|
renderContext = DrawingContext(size: displaySize, scale: UIScreenScale, premultiplied: true, clear: true)
|
||||||
|
}
|
||||||
|
|
||||||
self.item = item
|
self.item = item
|
||||||
self.instance = instance
|
self.instance = resolvedInstance
|
||||||
|
self.renderContext = renderContext
|
||||||
|
|
||||||
self.frameCount = Int(instance.frameCount)
|
self.frameCount = Int(self.instance.frameCount)
|
||||||
self.fps = Double(instance.frameRate)
|
self.fps = Double(self.instance.frameRate)
|
||||||
|
|
||||||
self.renderContext = DrawingContext(size: instance.dimensions, scale: UIScreenScale, premultiplied: true, clear: true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func draw() -> UIImage? {
|
func draw() -> UIImage? {
|
||||||
@ -56,34 +57,23 @@ private final class ManagedAnimationState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ManagedAnimationActionAtEnd {
|
struct ManagedAnimationFrameRange: Equatable {
|
||||||
case pause
|
var startFrame: Int
|
||||||
case advance
|
var endFrame: Int
|
||||||
case loop
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ManagedAnimationTrack: Equatable {
|
|
||||||
let frameRange: Range<Int>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ManagedAnimationItem: Equatable {
|
struct ManagedAnimationItem: Equatable {
|
||||||
let name: String
|
let name: String
|
||||||
var intro: ManagedAnimationTrack?
|
var frames: ManagedAnimationFrameRange
|
||||||
var loop: ManagedAnimationTrack?
|
|
||||||
var outro: ManagedAnimationTrack?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final class ManagedAnimationNode: ASDisplayNode {
|
class ManagedAnimationNode: ASDisplayNode {
|
||||||
let intrinsicSize: CGSize
|
let intrinsicSize: CGSize
|
||||||
|
|
||||||
private let imageNode: ASImageNode
|
private let imageNode: ASImageNode
|
||||||
private let displayLink: CADisplayLink
|
private let displayLink: CADisplayLink
|
||||||
|
|
||||||
private var items: [ManagedAnimationState] = []
|
private var state: ManagedAnimationState?
|
||||||
|
|
||||||
var currentItemName: String? {
|
|
||||||
return self.items.first?.item.name
|
|
||||||
}
|
|
||||||
|
|
||||||
init(size: CGSize) {
|
init(size: CGSize) {
|
||||||
self.intrinsicSize = size
|
self.intrinsicSize = size
|
||||||
@ -121,136 +111,174 @@ final class ManagedAnimationNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func updateAnimation() {
|
private func updateAnimation() {
|
||||||
guard let item = self.items.first else {
|
guard let state = self.state else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let timestamp = CACurrentMediaTime()
|
let timestamp = CACurrentMediaTime()
|
||||||
|
|
||||||
var startTime: Double
|
var startTime: Double
|
||||||
let maybeTrackState: ManagedAnimationTrackState?
|
if let current = state.startTime {
|
||||||
if let current = item.startTime {
|
|
||||||
startTime = current
|
startTime = current
|
||||||
} else {
|
} else {
|
||||||
startTime = timestamp
|
startTime = timestamp
|
||||||
item.startTime = startTime
|
state.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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let trackState = maybeTrackState else {
|
let fps = state.fps
|
||||||
self.items.removeFirst()
|
let frameRange = state.item.frames
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var fps = item.fps
|
|
||||||
|
|
||||||
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
|
let duration: Double = 0.3
|
||||||
var t = (timestamp - startTime) / duration
|
var t = (timestamp - startTime) / duration
|
||||||
t = max(0.0, t)
|
t = max(0.0, t)
|
||||||
t = min(1.0, t)
|
t = min(1.0, t)
|
||||||
let frameOffset = Int(Double(startFrame) * (1.0 - t) + Double(endFrame) * t)
|
let frameOffset = Int(Double(frameRange.startFrame) * (1.0 - t) + Double(frameRange.startFrame) * t)
|
||||||
let lowerBound = min(track.frameRange.lowerBound, item.frameCount - 1)
|
let lowerBound = min(frameRange.startFrame, state.frameCount - 1)
|
||||||
let upperBound = min(track.frameRange.upperBound, item.frameCount)
|
let upperBound = min(frameRange.endFrame, state.frameCount - 1)
|
||||||
frameIndex = max(lowerBound, min(upperBound, frameOffset))
|
let 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 {
|
if state.frameIndex != frameIndex {
|
||||||
item.frameIndex = frameIndex
|
state.frameIndex = frameIndex
|
||||||
if let image = item.draw() {
|
if let image = state.draw() {
|
||||||
self.imageNode.image = image
|
self.imageNode.image = image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func switchTo(_ item: ManagedAnimationItem, noOutro: Bool = false) {
|
func trackTo(item: ManagedAnimationItem, frameIndex: Int) {
|
||||||
if let state = ManagedAnimationState(item: item) {
|
if let state = self.state, state.item.name == item.name {
|
||||||
if let last = self.items.last {
|
self.state = ManagedAnimationState(displaySize: self.intrinsicSize, item: item, current: state)
|
||||||
if last.item.name == item.name {
|
} else {
|
||||||
return
|
self.state = ManagedAnimationState(displaySize: self.intrinsicSize, item: item, current: nil)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if let first = self.items.first {
|
|
||||||
if noOutro {
|
|
||||||
first.item.outro = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.items.append(state)
|
|
||||||
self.updateAnimation()
|
self.updateAnimation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func trackTo(frameIndex: Int) {
|
enum ManagedMonkeyAnimationState: Equatable {
|
||||||
if let first = self.items.first {
|
case idle
|
||||||
first.startTime = CACurrentMediaTime()
|
case eyesClosed
|
||||||
first.trackingFrameState = (first.frameIndex ?? 0, frameIndex)
|
case peeking
|
||||||
self.updateAnimation()
|
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 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 TelegramPresentationData
|
||||||
import PresentationDataUtils
|
import PresentationDataUtils
|
||||||
import TelegramCore
|
import TelegramCore
|
||||||
|
import AnimatedStickerNode
|
||||||
|
|
||||||
public enum TwoFactorDataInputMode {
|
public enum TwoFactorDataInputMode {
|
||||||
case password
|
case password
|
||||||
case emailAddress(password: String)
|
case emailAddress(password: String, hint: String)
|
||||||
case emailConfirmation(password: String?, emailPattern: String)
|
case updateEmailAddress(password: String)
|
||||||
|
case emailConfirmation(passwordAndHint: (String, String)?, emailPattern: String, codeLength: Int?)
|
||||||
case passwordHint(password: String)
|
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 {
|
public final class TwoFactorDataInputScreen: ViewController {
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private var presentationData: PresentationData
|
private var presentationData: PresentationData
|
||||||
private let mode: TwoFactorDataInputMode
|
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.context = context
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
|
self.stateUpdated = stateUpdated
|
||||||
|
|
||||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
|
||||||
@ -124,6 +76,40 @@ public final class TwoFactorDataInputScreen: ViewController {
|
|||||||
if values[0].isEmpty {
|
if values[0].isEmpty {
|
||||||
return
|
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 && controller !== strongSelf {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
controllers.append(TwoFactorDataInputScreen(context: strongSelf.context, mode: .passwordHint(password: values[0]), stateUpdated: strongSelf.stateUpdated))
|
||||||
|
navigationController.setViewControllers(controllers, animated: true)
|
||||||
|
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 {
|
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -136,9 +122,43 @@ public final class TwoFactorDataInputScreen: ViewController {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
controllers.append(TwoFactorDataInputScreen(context: strongSelf.context, mode: .passwordHint(password: values[0])))
|
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)
|
navigationController.setViewControllers(controllers, animated: true)
|
||||||
case let .emailAddress(password):
|
} 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 {
|
guard let text = (strongSelf.displayNode as! TwoFactorDataInputScreenNode).inputText.first, !text.isEmpty else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -156,7 +176,7 @@ public final class TwoFactorDataInputScreen: ViewController {
|
|||||||
switch result {
|
switch result {
|
||||||
case .none:
|
case .none:
|
||||||
break
|
break
|
||||||
case let .password(password, pendingEmail):
|
case let .password(_, pendingEmail):
|
||||||
if let pendingEmail = pendingEmail {
|
if let pendingEmail = pendingEmail {
|
||||||
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
||||||
return
|
return
|
||||||
@ -170,7 +190,7 @@ public final class TwoFactorDataInputScreen: ViewController {
|
|||||||
}
|
}
|
||||||
return true
|
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)
|
navigationController.setViewControllers(controllers, animated: true)
|
||||||
} else {
|
} else {
|
||||||
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
||||||
@ -263,19 +283,34 @@ public final class TwoFactorDataInputScreen: ViewController {
|
|||||||
return
|
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
|
}, skipAction: { [weak self] in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch strongSelf.mode {
|
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: [
|
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: {
|
TextAlertAction(type: .destructiveAction, title: strongSelf.presentationData.strings.TwoFactorSetup_Email_SkipConfirmationSkip, action: {
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
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: nil))
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak statusController] result in
|
||||||
|
statusController?.dismiss()
|
||||||
|
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch result {
|
||||||
|
case .none:
|
||||||
|
break
|
||||||
|
case .password:
|
||||||
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -290,11 +325,29 @@ public final class TwoFactorDataInputScreen: ViewController {
|
|||||||
}
|
}
|
||||||
controllers.append(TwoFactorAuthSplashScreen(context: strongSelf.context, mode: .done))
|
controllers.append(TwoFactorAuthSplashScreen(context: strongSelf.context, mode: .done))
|
||||||
navigationController.setViewControllers(controllers, animated: true)
|
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: {})
|
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})
|
||||||
]), in: .window(.root))
|
]), in: .window(.root))
|
||||||
case let .passwordHint(password):
|
case let .passwordHint(password):
|
||||||
strongSelf.setPassword(password: password, hint: "")
|
strongSelf.push(TwoFactorDataInputScreen(context: strongSelf.context, mode: .emailAddress(password: password, hint: ""), stateUpdated: strongSelf.stateUpdated))
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -303,8 +356,8 @@ public final class TwoFactorDataInputScreen: ViewController {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch strongSelf.mode {
|
switch strongSelf.mode {
|
||||||
case let .emailConfirmation(password, _):
|
case let .emailConfirmation(passwordAndHint, _, _):
|
||||||
if let password = password {
|
if let (password, hint) = passwordAndHint {
|
||||||
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -317,7 +370,7 @@ public final class TwoFactorDataInputScreen: ViewController {
|
|||||||
}
|
}
|
||||||
return true
|
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)
|
navigationController.setViewControllers(controllers, animated: true)
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
@ -356,41 +409,6 @@ public final class TwoFactorDataInputScreen: ViewController {
|
|||||||
self.displayNodeDidLoad()
|
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) {
|
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||||
super.containerLayoutUpdated(layout, transition: transition)
|
super.containerLayoutUpdated(layout, transition: transition)
|
||||||
|
|
||||||
@ -612,7 +630,8 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
private let navigationBackgroundNode: ASDisplayNode
|
private let navigationBackgroundNode: ASDisplayNode
|
||||||
private let navigationSeparatorNode: ASDisplayNode
|
private let navigationSeparatorNode: ASDisplayNode
|
||||||
private let scrollNode: ASScrollNode
|
private let scrollNode: ASScrollNode
|
||||||
private let animationNode: ManagedAnimationNode
|
private var animatedStickerNode: AnimatedStickerNode?
|
||||||
|
private var monkeyNode: ManagedMonkeyAnimationNode?
|
||||||
private let titleNode: ImmediateTextNode
|
private let titleNode: ImmediateTextNode
|
||||||
private let textNode: ImmediateTextNode
|
private let textNode: ImmediateTextNode
|
||||||
private let skipActionTitleNode: ImmediateTextNode
|
private let skipActionTitleNode: ImmediateTextNode
|
||||||
@ -647,7 +666,24 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
self.scrollNode = ASScrollNode()
|
self.scrollNode = ASScrollNode()
|
||||||
self.scrollNode.canCancelAllTouchesInViews = true
|
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 title: String
|
||||||
let text: NSAttributedString
|
let text: NSAttributedString
|
||||||
@ -664,8 +700,6 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
|
|
||||||
switch mode {
|
switch mode {
|
||||||
case .password:
|
case .password:
|
||||||
self.animationNode.switchTo(animationIdle)
|
|
||||||
|
|
||||||
title = presentationData.strings.TwoFactorSetup_Password_Title
|
title = presentationData.strings.TwoFactorSetup_Password_Title
|
||||||
text = NSAttributedString(string: "", font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
|
text = NSAttributedString(string: "", font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
|
||||||
buttonText = presentationData.strings.TwoFactorSetup_Password_Action
|
buttonText = presentationData.strings.TwoFactorSetup_Password_Action
|
||||||
@ -692,9 +726,7 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
toggleTextHidden?(node)
|
toggleTextHidden?(node)
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
case .emailAddress:
|
case .emailAddress, .updateEmailAddress:
|
||||||
self.animationNode.switchTo(animationTracking)
|
|
||||||
|
|
||||||
title = presentationData.strings.TwoFactorSetup_Email_Title
|
title = presentationData.strings.TwoFactorSetup_Email_Title
|
||||||
text = NSAttributedString(string: presentationData.strings.TwoFactorSetup_Email_Text, font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
|
text = NSAttributedString(string: presentationData.strings.TwoFactorSetup_Email_Text, font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
|
||||||
buttonText = presentationData.strings.TwoFactorSetup_Email_Action
|
buttonText = presentationData.strings.TwoFactorSetup_Email_Action
|
||||||
@ -712,9 +744,7 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
toggleTextHidden?(node)
|
toggleTextHidden?(node)
|
||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
case let .emailConfirmation(_, emailPattern):
|
case let .emailConfirmation(_, emailPattern, _):
|
||||||
self.animationNode.switchTo(animationMail)
|
|
||||||
|
|
||||||
title = presentationData.strings.TwoFactorSetup_EmailVerification_Title
|
title = presentationData.strings.TwoFactorSetup_EmailVerification_Title
|
||||||
let (rawText, ranges) = presentationData.strings.TwoFactorSetup_EmailVerification_Text(emailPattern)
|
let (rawText, ranges) = presentationData.strings.TwoFactorSetup_EmailVerification_Text(emailPattern)
|
||||||
|
|
||||||
@ -742,8 +772,6 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
case .passwordHint:
|
case .passwordHint:
|
||||||
self.animationNode.switchTo(animationHint)
|
|
||||||
|
|
||||||
title = presentationData.strings.TwoFactorSetup_Hint_Title
|
title = presentationData.strings.TwoFactorSetup_Hint_Title
|
||||||
|
|
||||||
text = NSAttributedString(string: presentationData.strings.TwoFactorSetup_Hint_Text, font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
|
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.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.titleNode)
|
||||||
self.scrollNode.addSubnode(self.textNode)
|
self.scrollNode.addSubnode(self.textNode)
|
||||||
self.scrollNode.addSubnode(self.skipActionTitleNode)
|
self.scrollNode.addSubnode(self.skipActionTitleNode)
|
||||||
@ -880,7 +909,13 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
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
|
focused = { [weak self] node in
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
@ -895,7 +930,7 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty })
|
let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty })
|
||||||
switch strongSelf.mode {
|
/*switch strongSelf.mode {
|
||||||
case .password:
|
case .password:
|
||||||
if !hasText {
|
if !hasText {
|
||||||
if strongSelf.animationNode.currentItemName == animationPeek.name {
|
if strongSelf.animationNode.currentItemName == animationPeek.name {
|
||||||
@ -942,25 +977,30 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
updated = { [weak self] _ in
|
updated = { [weak self] _ in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch strongSelf.mode {
|
switch strongSelf.mode {
|
||||||
case .emailAddress:
|
case .emailAddress, .updateEmailAddress:
|
||||||
let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty })
|
let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty })
|
||||||
strongSelf.buttonNode.isHidden = !hasText
|
strongSelf.buttonNode.isHidden = !hasText
|
||||||
strongSelf.skipActionTitleNode.isHidden = hasText
|
strongSelf.skipActionTitleNode.isHidden = hasText
|
||||||
strongSelf.skipActionButtonNode.isHidden = hasText
|
strongSelf.skipActionButtonNode.isHidden = hasText
|
||||||
case .emailConfirmation:
|
case let .emailConfirmation(_, _, codeLength):
|
||||||
let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty })
|
let text = strongSelf.inputNodes[0].text
|
||||||
|
let hasText = !text.isEmpty
|
||||||
strongSelf.buttonNode.isHidden = !hasText
|
strongSelf.buttonNode.isHidden = !hasText
|
||||||
strongSelf.changeEmailActionTitleNode.isHidden = hasText
|
strongSelf.changeEmailActionTitleNode.isHidden = hasText
|
||||||
strongSelf.changeEmailActionButtonNode.isHidden = hasText
|
strongSelf.changeEmailActionButtonNode.isHidden = hasText
|
||||||
strongSelf.resendCodeActionTitleNode.isHidden = hasText
|
strongSelf.resendCodeActionTitleNode.isHidden = hasText
|
||||||
strongSelf.resendCodeActionButtonNode.isHidden = hasText
|
strongSelf.resendCodeActionButtonNode.isHidden = hasText
|
||||||
|
|
||||||
|
if let codeLength = codeLength, text.count == codeLength {
|
||||||
|
action()
|
||||||
|
}
|
||||||
case .passwordHint:
|
case .passwordHint:
|
||||||
let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty })
|
let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty })
|
||||||
strongSelf.buttonNode.isHidden = !hasText
|
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))
|
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 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))
|
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 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)
|
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)
|
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)
|
transition.updateFrameAdditive(node: self.titleNode, frame: titleFrame)
|
||||||
let textFrame: CGRect
|
let textFrame: CGRect
|
||||||
|
|||||||
@ -54,7 +54,8 @@ public final class TwoFactorAuthSplashScreen: ViewController {
|
|||||||
}
|
}
|
||||||
switch strongSelf.mode {
|
switch strongSelf.mode {
|
||||||
case .intro:
|
case .intro:
|
||||||
strongSelf.push(TwoFactorDataInputScreen(context: strongSelf.context, mode: .password))
|
strongSelf.push(TwoFactorDataInputScreen(context: strongSelf.context, mode: .password, stateUpdated: { _ in
|
||||||
|
}))
|
||||||
case .done:
|
case .done:
|
||||||
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
||||||
return
|
return
|
||||||
|
|||||||
@ -268,6 +268,7 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
|
|||||||
|
|
||||||
var replaceControllerImpl: ((ViewController, Bool) -> Void)?
|
var replaceControllerImpl: ((ViewController, Bool) -> Void)?
|
||||||
var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)?
|
var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)?
|
||||||
|
var dismissImpl: (() -> Void)?
|
||||||
|
|
||||||
let actionsDisposable = DisposableSet()
|
let actionsDisposable = DisposableSet()
|
||||||
|
|
||||||
@ -629,7 +630,8 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
|
|||||||
state.checking = false
|
state.checking = false
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
dataPromise.set(.single(TwoStepVerificationUnlockSettingsControllerData.access(configuration: .notSet(pendingEmail: nil))))
|
//dataPromise.set(.single(TwoStepVerificationUnlockSettingsControllerData.access(configuration: .notSet(pendingEmail: nil))))
|
||||||
|
dismissImpl?()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
})]), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
})]), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||||
@ -645,6 +647,8 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
|
|||||||
case .access:
|
case .access:
|
||||||
break
|
break
|
||||||
case let .manage(password, emailSet, _, hasSecureValues):
|
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
|
let controller = SetupTwoStepVerificationController(context: context, initialState: .addEmail(hadRecoveryEmail: emailSet, hasSecureValues: hasSecureValues, password: password), stateUpdated: { update, shouldDismiss, controller in
|
||||||
switch update {
|
switch update {
|
||||||
case .noPassword:
|
case .noPassword:
|
||||||
@ -822,6 +826,9 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
|
|||||||
controller.present(c, in: .window(.root), with: p)
|
controller.present(c, in: .window(.root), with: p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dismissImpl = { [weak controller] in
|
||||||
|
controller?.dismiss()
|
||||||
|
}
|
||||||
initialFocusImpl = { [weak controller] in
|
initialFocusImpl = { [weak controller] in
|
||||||
guard let controller = controller, controller.didAppearOnce else {
|
guard let controller = controller, controller.didAppearOnce else {
|
||||||
return
|
return
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user