diff --git a/TelegramUI/ChatControllerBackgroundNode.swift b/TelegramUI/ChatControllerBackgroundNode.swift index 8d7f3f7cac..6e537ab625 100644 --- a/TelegramUI/ChatControllerBackgroundNode.swift +++ b/TelegramUI/ChatControllerBackgroundNode.swift @@ -73,7 +73,7 @@ private var serviceBackgroundColorForWallpaper: (TelegramWallpaper, UIColor)? func chatControllerBackgroundImage(wallpaper: TelegramWallpaper, mediaBox: MediaBox, composed: Bool = true) -> UIImage? { var backgroundImage: UIImage? - if wallpaper == backgroundImageForWallpaper?.0, (wallpaper.settings?.blur ?? false) == backgroundImageForWallpaper?.1 { + if composed && wallpaper == backgroundImageForWallpaper?.0, (wallpaper.settings?.blur ?? false) == backgroundImageForWallpaper?.1 { backgroundImage = backgroundImageForWallpaper?.2 } else { switch wallpaper { @@ -125,7 +125,7 @@ func chatControllerBackgroundImage(wallpaper: TelegramWallpaper, mediaBox: Media } } } - if let backgroundImage = backgroundImage { + if let backgroundImage = backgroundImage, composed { backgroundImageForWallpaper = (wallpaper, (wallpaper.settings?.blur ?? false), backgroundImage) } } diff --git a/TelegramUI/ChatListItem.swift b/TelegramUI/ChatListItem.swift index 9192a4e187..fa075cdcfb 100644 --- a/TelegramUI/ChatListItem.swift +++ b/TelegramUI/ChatListItem.swift @@ -162,8 +162,8 @@ private let readIcon = ItemListRevealOptionIcon.animation(animation: "anim_read" private let unreadIcon = ItemListRevealOptionIcon.animation(animation: "anim_unread", scale: 0.33333, offset: 0.0, keysToColor: ["Oval.Oval.Stroke 1"], flip: false) private let archiveIcon = ItemListRevealOptionIcon.animation(animation: "anim_archive", scale: 0.33333, offset: 2.0, keysToColor: ["box2.box2.Fill 1"], flip: false) private let unarchiveIcon = ItemListRevealOptionIcon.animation(animation: "anim_unarchive", scale: 0.16214, offset: -9.0, keysToColor: ["box2.box2.Fill 1"], flip: false) -private let hideIcon = ItemListRevealOptionIcon.animation(animation: "anim_hide", scale: 0.33333, offset: 0.0, keysToColor: ["Path 2.Path 2.Fill 1"], flip: false) -private let unhideIcon = ItemListRevealOptionIcon.animation(animation: "anim_hide", scale: 0.33333, offset: 0.0, keysToColor: ["Path 2.Path 2.Fill 1"], flip: true) +private let hideIcon = ItemListRevealOptionIcon.animation(animation: "anim_hide", scale: 0.33333, offset: 2.0, keysToColor: ["Path 2.Path 2.Fill 1"], flip: false) +private let unhideIcon = ItemListRevealOptionIcon.animation(animation: "anim_hide", scale: 0.33333, offset: -20.0, keysToColor: ["Path 2.Path 2.Fill 1"], flip: true) private enum RevealOptionKey: Int32 { case pin diff --git a/TelegramUI/PasscodeEntryController.swift b/TelegramUI/PasscodeEntryController.swift index bd67d8ed30..a9f7fc02a1 100644 --- a/TelegramUI/PasscodeEntryController.swift +++ b/TelegramUI/PasscodeEntryController.swift @@ -28,6 +28,7 @@ final public class PasscodeEntryController: ViewController { private let arguments: PasscodeEntryControllerPresentationArguments public var presentationCompleted: (() -> Void)? + public var completed: (() -> Void)? private let biometricsDisposable = MetaDisposable() @@ -102,18 +103,22 @@ final public class PasscodeEntryController: ViewController { } if succeed { - let _ = (strongSelf.context.sharedContext.accountManager.transaction { transaction -> Void in - var data = transaction.getAccessChallengeData().withUpdatedAutolockDeadline(nil) - switch data { - case .none: - break - case let .numericalPassword(value, timeout, _): - data = .numericalPassword(value: value, timeout: timeout, attempts: nil) - case let .plaintextPassword(value, timeout, _): - data = .plaintextPassword(value: value, timeout: timeout, attempts: nil) - } - transaction.setAccessChallengeData(data) - }).start() + if let completed = strongSelf.completed { + completed() + } else { + let _ = (strongSelf.context.sharedContext.accountManager.transaction { transaction -> Void in + var data = transaction.getAccessChallengeData().withUpdatedAutolockDeadline(nil) + switch data { + case .none: + break + case let .numericalPassword(value, timeout, _): + data = .numericalPassword(value: value, timeout: timeout, attempts: nil) + case let .plaintextPassword(value, timeout, _): + data = .plaintextPassword(value: value, timeout: timeout, attempts: nil) + } + transaction.setAccessChallengeData(data) + }).start() + } } else { let _ = (strongSelf.context.sharedContext.accountManager.transaction({ transaction -> AccessChallengeAttempts in var data = transaction.getAccessChallengeData() @@ -160,11 +165,14 @@ final public class PasscodeEntryController: ViewController { self.controllerNode.activateInput() if self.arguments.animated { - Queue.mainQueue().after(0.5) { - serviceSoundManager.playLockSound() + let iconFrame = self.arguments.lockIconInitialFrame() + if !iconFrame.isEmpty { + Queue.mainQueue().after(0.5) { + serviceSoundManager.playLockSound() + } } - self.controllerNode.animateIn(iconFrame: self.arguments.lockIconInitialFrame(), completion: { [weak self] in + self.controllerNode.animateIn(iconFrame: iconFrame, completion: { [weak self] in self?.presentationCompleted?() }) } else { diff --git a/TelegramUI/PasscodeEntryControllerNode.swift b/TelegramUI/PasscodeEntryControllerNode.swift index c7f4e89a53..967586e0b3 100644 --- a/TelegramUI/PasscodeEntryControllerNode.swift +++ b/TelegramUI/PasscodeEntryControllerNode.swift @@ -6,7 +6,7 @@ import Postbox import TelegramCore private let titleFont = Font.regular(20.0) -private let subtitleFont = Font.regular(17.0) +private let subtitleFont = Font.regular(15.0) private let buttonFont = Font.regular(17.0) final class PasscodeEntryControllerNode: ASDisplayNode { @@ -177,15 +177,9 @@ final class PasscodeEntryControllerNode: ASDisplayNode { func updateInvalidAttempts(_ attempts: AccessChallengeAttempts?, animated: Bool = false) { self.invalidAttempts = attempts if let attempts = attempts { - let text: NSAttributedString - if attempts.count >= 6 { - if self.shouldWaitBeforeNextAttempt() { - text = NSAttributedString(string: self.strings.PasscodeSettings_TryAgainIn1Minute, font: subtitleFont, textColor: .white) - } else { - text = NSAttributedString(string: "") - } - } else { - text = NSAttributedString(string: self.strings.PasscodeSettings_FailedAttempts(attempts.count), font: subtitleFont, textColor: .white) + var text = NSAttributedString(string: "") + if attempts.count >= 6 && self.shouldWaitBeforeNextAttempt() { + text = NSAttributedString(string: self.strings.PasscodeSettings_TryAgainIn1Minute, font: subtitleFont, textColor: .white) } self.subtitleNode.setAttributedText(text, animation: animated ? .crossFade : .none, completion: {}) @@ -212,8 +206,10 @@ final class PasscodeEntryControllerNode: ASDisplayNode { } }) self.backgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) - self.iconNode.animateIn(fromScale: 0.416) - self.iconNode.layer.animatePosition(from: iconFrame.center.offsetBy(dx: 6.0, dy: 6.0), to: self.iconNode.layer.position, duration: 0.45) + if !iconFrame.isEmpty { + self.iconNode.animateIn(fromScale: 0.416) + self.iconNode.layer.animatePosition(from: iconFrame.center.offsetBy(dx: 6.0, dy: 6.0), to: self.iconNode.layer.position, duration: 0.45) + } self.statusBar.layer.removeAnimation(forKey: "opacity") self.statusBar.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) @@ -274,6 +270,10 @@ final class PasscodeEntryControllerNode: ASDisplayNode { self.updateBackground() } + if layout.size.width == 320.0 { + self.iconNode.alpha = 0.0 + } + let bounds = CGRect(origin: CGPoint(), size: layout.size) transition.updateFrame(node: self.backgroundNode, frame: bounds) transition.updateFrame(view: self.effectView, frame: bounds) @@ -289,8 +289,12 @@ final class PasscodeEntryControllerNode: ASDisplayNode { let titleSize = self.titleNode.updateLayout(layout: layout, transition: transition) transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: 0.0, y: passcodeLayout.titleOffset), size: titleSize)) + var subtitleOffset = passcodeLayout.subtitleOffset + if case .alphanumeric = self.passcodeType { + subtitleOffset = 16.0 + } let subtitleSize = self.subtitleNode.updateLayout(layout: layout, transition: transition) - transition.updateFrame(node: self.subtitleNode, frame: CGRect(origin: CGPoint(x: 0.0, y: inputFieldFrame.maxY + passcodeLayout.subtitleOffset), size: subtitleSize)) + transition.updateFrame(node: self.subtitleNode, frame: CGRect(origin: CGPoint(x: 0.0, y: inputFieldFrame.maxY + subtitleOffset), size: subtitleSize)) let (keyboardFrame, keyboardButtonSize) = self.keyboardNode.updateLayout(layout: passcodeLayout, transition: transition) transition.updateFrame(node: self.keyboardNode, frame: CGRect(origin: CGPoint(), size: layout.size)) @@ -311,7 +315,7 @@ final class PasscodeEntryControllerNode: ASDisplayNode { if bottomInset > 0 && self.keyboardNode.alpha < 1.0 { biometricY = inputFieldFrame.maxY + floor((layout.size.height - bottomInset - inputFieldFrame.maxY - biometricIcon.size.height) / 2.0) } else { - biometricY = keyboardFrame.maxY + 30.0 + biometricY = keyboardFrame.maxY + passcodeLayout.keyboard.biometricsOffset } transition.updateFrame(node: self.biometricButtonNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - biometricIcon.size.width) / 2.0), y: biometricY), size: biometricIcon.size)) } diff --git a/TelegramUI/PasscodeEntryInputFieldNode.swift b/TelegramUI/PasscodeEntryInputFieldNode.swift index f4e4724e0b..9176139c26 100644 --- a/TelegramUI/PasscodeEntryInputFieldNode.swift +++ b/TelegramUI/PasscodeEntryInputFieldNode.swift @@ -309,7 +309,10 @@ final class PasscodeEntryInputFieldNode: ASDisplayNode, UITextFieldDelegate { transition.updateFrame(node: node, frame: dotFrame) } - let inset: CGFloat = 50.0 + var inset: CGFloat = 50.0 + if !self.useCustomNumpad { + inset = 16.0 + } let fieldFrame = CGRect(x: inset, y: origin.y, width: layout.layout.size.width - inset * 2.0, height: fieldHeight) transition.updateFrame(node: self.borderNode, frame: fieldFrame) transition.updateFrame(node: self.textFieldNode, frame: fieldFrame.insetBy(dx: 13.0, dy: 0.0)) diff --git a/TelegramUI/PasscodeLayout.swift b/TelegramUI/PasscodeLayout.swift index 00c433f515..cfcdf5106b 100644 --- a/TelegramUI/PasscodeLayout.swift +++ b/TelegramUI/PasscodeLayout.swift @@ -10,6 +10,7 @@ struct PasscodeKeyboardLayout { let verticalFourth: CGFloat let size: CGSize let topOffset: CGFloat + let biometricsOffset: CGFloat fileprivate init(metrics: DeviceMetrics?) { if let metrics = metrics { @@ -23,6 +24,7 @@ struct PasscodeKeyboardLayout { self.verticalFourth = 264.0 self.size = CGSize(width: 265.0, height: 339.0) self.topOffset = 0.0 + self.biometricsOffset = 0.0 case .iPhone5: self.buttonSize = 75.0 self.horizontalSecond = 95.0 @@ -31,7 +33,8 @@ struct PasscodeKeyboardLayout { self.verticalThird = 176.0 self.verticalFourth = 264.0 self.size = CGSize(width: 265.0, height: 339.0) - self.topOffset = 0.0 + self.topOffset = 155.0 + self.biometricsOffset = 23.0 case .iPhone6: self.buttonSize = 75.0 self.horizontalSecond = 103.0 @@ -40,7 +43,8 @@ struct PasscodeKeyboardLayout { self.verticalThird = 180.0 self.verticalFourth = 270.0 self.size = CGSize(width: 281.0, height: 348.0) - self.topOffset = 0.0 + self.topOffset = 221.0 + self.biometricsOffset = 30.0 case .iPhone6Plus: self.buttonSize = 85.0 self.horizontalSecond = 115.0 @@ -50,6 +54,7 @@ struct PasscodeKeyboardLayout { self.verticalFourth = 300.0 self.size = CGSize(width: 315.0, height: 385.0) self.topOffset = 226.0 + self.biometricsOffset = 30.0 case .iPhoneX: self.buttonSize = 75.0 self.horizontalSecond = 103.0 @@ -59,6 +64,7 @@ struct PasscodeKeyboardLayout { self.verticalFourth = 273.0 self.size = CGSize(width: 281.0, height: 348.0) self.topOffset = 294.0 + self.biometricsOffset = 30.0 case .iPhoneXSMax: self.buttonSize = 85.0 self.horizontalSecond = 115.0 @@ -68,6 +74,7 @@ struct PasscodeKeyboardLayout { self.verticalFourth = 300.0 self.size = CGSize(width: 315.0, height: 385.0) self.topOffset = 329.0 + self.biometricsOffset = 30.0 case .iPad, .iPadPro10Inch, .iPadPro11Inch, .iPadPro, .iPadPro3rdGen: self.buttonSize = 81.0 self.horizontalSecond = 106.0 @@ -77,6 +84,7 @@ struct PasscodeKeyboardLayout { self.verticalFourth = 303.0 self.size = CGSize(width: 293.0, height: 384.0) self.topOffset = 0.0 + self.biometricsOffset = 30.0 } } else { self.buttonSize = 75.0 @@ -87,6 +95,7 @@ struct PasscodeKeyboardLayout { self.verticalFourth = 264.0 self.size = CGSize(width: 265.0, height: 339.0) self.topOffset = 0.0 + self.biometricsOffset = 30.0 } } } @@ -106,17 +115,17 @@ struct PasscodeLayout { if let metrics = metrics { switch metrics { case .iPhone4: - self.titleOffset = 0.0 + self.titleOffset = 30.0 self.subtitleOffset = 0.0 - self.inputFieldOffset = 0.0 + self.inputFieldOffset = 70.0 case .iPhone5: - self.titleOffset = 0.0 - self.subtitleOffset = 0.0 - self.inputFieldOffset = 0.0 + self.titleOffset = 50.0 + self.subtitleOffset = -7.0 + self.inputFieldOffset = 90.0 case .iPhone6: - self.titleOffset = 0.0 - self.subtitleOffset = 0.0 - self.inputFieldOffset = 0.0 + self.titleOffset = 100.0 + self.subtitleOffset = -3.0 + self.inputFieldOffset = 144.0 case .iPhone6Plus: self.titleOffset = 112.0 self.subtitleOffset = -6.0 diff --git a/TelegramUI/PasscodeOptionsController.swift b/TelegramUI/PasscodeOptionsController.swift index 92d5ed6687..57051ed6d8 100644 --- a/TelegramUI/PasscodeOptionsController.swift +++ b/TelegramUI/PasscodeOptionsController.swift @@ -7,20 +7,16 @@ import LegacyComponents import LocalAuthentication private final class PasscodeOptionsControllerArguments { - let turnPasscodeOn: () -> Void let turnPasscodeOff: () -> Void let changePasscode: () -> Void let changePasscodeTimeout: () -> Void let changeTouchId: (Bool) -> Void - let toggleSimplePasscode: (Bool) -> Void - init(turnPasscodeOn: @escaping () -> Void, turnPasscodeOff: @escaping () -> Void, changePasscode: @escaping () -> Void, changePasscodeTimeout: @escaping () -> Void, changeTouchId: @escaping (Bool) -> Void, toggleSimplePasscode: @escaping (Bool) -> Void) { - self.turnPasscodeOn = turnPasscodeOn + init(turnPasscodeOff: @escaping () -> Void, changePasscode: @escaping () -> Void, changePasscodeTimeout: @escaping () -> Void, changeTouchId: @escaping (Bool) -> Void) { self.turnPasscodeOff = turnPasscodeOff self.changePasscode = changePasscode self.changePasscodeTimeout = changePasscodeTimeout self.changeTouchId = changeTouchId - self.toggleSimplePasscode = toggleSimplePasscode } } @@ -36,13 +32,12 @@ private enum PasscodeOptionsEntry: ItemListNodeEntry { case autoLock(PresentationTheme, String, String) case touchId(PresentationTheme, String, Bool) - case simplePasscode(PresentationTheme, String, Bool) var section: ItemListSectionId { switch self { case .togglePasscode, .changePasscode, .settingInfo: return PasscodeOptionsSection.setting.rawValue - case .autoLock, .touchId, .simplePasscode: + case .autoLock, .touchId: return PasscodeOptionsSection.options.rawValue } } @@ -59,8 +54,6 @@ private enum PasscodeOptionsEntry: ItemListNodeEntry { return 3 case .touchId: return 4 - case .simplePasscode: - return 5 } } @@ -96,12 +89,6 @@ private enum PasscodeOptionsEntry: ItemListNodeEntry { } else { return false } - case let .simplePasscode(lhsTheme, lhsText, lhsValue): - if case let .simplePasscode(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { - return true - } else { - return false - } } } @@ -115,8 +102,6 @@ private enum PasscodeOptionsEntry: ItemListNodeEntry { return ItemListActionItem(theme: theme, title: title, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { if value { arguments.turnPasscodeOff() - } else { - arguments.turnPasscodeOn() } }) case let .changePasscode(theme, title): @@ -133,10 +118,6 @@ private enum PasscodeOptionsEntry: ItemListNodeEntry { return ItemListSwitchItem(theme: theme, title: title, value: value, sectionId: self.section, style: .blocks, updated: { value in arguments.changeTouchId(value) }) - case let .simplePasscode(theme, title, value): - return ItemListSwitchItem(theme: theme, title: title, value: value, enableInteractiveChanges: false, sectionId: self.section, style: .blocks, updated: { value in - arguments.toggleSimplePasscode(value) - }) } } } @@ -225,6 +206,7 @@ func passcodeOptionsController(context: AccountContext) -> ViewController { var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments) -> Void)? var pushControllerImpl: ((ViewController) -> Void)? + var popControllerImpl: (() -> Void)? var replaceTopControllerImpl: ((ViewController, Bool) -> Void)? let actionsDisposable = DisposableSet() @@ -238,40 +220,7 @@ func passcodeOptionsController(context: AccountContext) -> ViewController { return PasscodeOptionsData(accessChallenge: accessChallenge, presentationSettings: passcodeSettings) }) - let arguments = PasscodeOptionsControllerArguments(turnPasscodeOn: { - var dismissImpl: (() -> Void)? - - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - - let legacyController = LegacyController(presentation: LegacyControllerPresentation.modal(animateIn: true), theme: presentationData.theme) - let controller = TGPasscodeEntryController(context: legacyController.context, style: TGPasscodeEntryControllerStyleDefault, mode: TGPasscodeEntryControllerModeSetupSimple, cancelEnabled: true, allowTouchId: false, attemptData: nil, completion: { result in - if let result = result { - let challenge = PostboxAccessChallengeData.numericalPassword(value: result, timeout: nil, attempts: nil) - let _ = (context.sharedContext.accountManager.transaction { transaction -> Void in - transaction.setAccessChallengeData(challenge) - updatePresentationPasscodeSettingsInternal(transaction: transaction, { current in - return current.withUpdatedAutolockTimeout(1 * 60 * 60) - }) - }).start() - - let _ = (passcodeOptionsDataPromise.get() - |> take(1)).start(next: { [weak passcodeOptionsDataPromise] data in - passcodeOptionsDataPromise?.set(.single(data.withUpdatedAccessChallenge(challenge).withUpdatedPresentationSettings(data.presentationSettings.withUpdatedAutolockTimeout(1 * 60 * 60)))) - }) - - dismissImpl?() - } else { - dismissImpl?() - } - })! - legacyController.bind(controller: controller) - legacyController.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .portrait, compactSize: .portrait) - legacyController.statusBar.statusBarStyle = .White - presentControllerImpl?(legacyController, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - dismissImpl = { [weak legacyController] in - legacyController?.dismiss() - } - }, turnPasscodeOff: { + let arguments = PasscodeOptionsControllerArguments(turnPasscodeOff: { let presentationData = context.sharedContext.currentPresentationData.with { $0 } let actionSheet = ActionSheetController(presentationTheme: presentationData.theme) actionSheet.setItemGroups([ActionSheetItemGroup(items: [ @@ -289,7 +238,7 @@ func passcodeOptionsController(context: AccountContext) -> ViewController { var innerReplaceTopControllerImpl: ((ViewController, Bool) -> Void)? let controller = PrivacyIntroController(context: context, mode: .passcode, proceedAction: { - let setupController = PasscodeSetupController(context: context, mode: .setup(.digits6)) + let setupController = PasscodeSetupController(context: context, mode: .setup(change: false, .digits6)) setupController.complete = { passcode, numerical in let _ = (context.sharedContext.accountManager.transaction({ transaction -> Void in var data = transaction.getAccessChallengeData() @@ -299,6 +248,8 @@ func passcodeOptionsController(context: AccountContext) -> ViewController { data = PostboxAccessChallengeData.plaintextPassword(value: passcode, timeout: data.autolockDeadline, attempts: nil) } transaction.setAccessChallengeData(data) + + updatePresentationPasscodeSettingsInternal(transaction: transaction, { $0.withUpdatedAutolockTimeout(1 * 60 * 60) }) }) |> deliverOnMainQueue).start(next: { _ in }, error: { _ in }, completed: { @@ -331,35 +282,23 @@ func passcodeOptionsController(context: AccountContext) -> ViewController { } }) |> deliverOnMainQueue).start(next: { isSimple in - var dismissImpl: (() -> Void)? - - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - - let legacyController = LegacyController(presentation: LegacyControllerPresentation.modal(animateIn: true), theme: presentationData.theme) - let controller = TGPasscodeEntryController(context: legacyController.context, style: TGPasscodeEntryControllerStyleDefault, mode: isSimple ? TGPasscodeEntryControllerModeSetupSimple : TGPasscodeEntryControllerModeSetupComplex, cancelEnabled: true, allowTouchId: false, attemptData: nil, completion: { result in - if let result = result { - let _ = context.sharedContext.accountManager.transaction({ transaction -> Void in - var data = transaction.getAccessChallengeData() - data = PostboxAccessChallengeData.numericalPassword(value: result, timeout: data.autolockDeadline, attempts: nil) - transaction.setAccessChallengeData(data) - }).start() - - let _ = (passcodeOptionsDataPromise.get() |> take(1)).start(next: { [weak passcodeOptionsDataPromise] data in - passcodeOptionsDataPromise?.set(.single(data.withUpdatedAccessChallenge(PostboxAccessChallengeData.numericalPassword(value: result, timeout: nil, attempts: nil)))) - }) - - dismissImpl?() - } else { - dismissImpl?() - } - })! - legacyController.bind(controller: controller) - legacyController.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .portrait, compactSize: .portrait) - legacyController.statusBar.statusBarStyle = .White - presentControllerImpl?(legacyController, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - dismissImpl = { [weak legacyController] in - legacyController?.dismiss() + let setupController = PasscodeSetupController(context: context, mode: .setup(change: true, .digits6)) + setupController.complete = { passcode, numerical in + let _ = (context.sharedContext.accountManager.transaction({ transaction -> Void in + var data = transaction.getAccessChallengeData() + if numerical { + data = PostboxAccessChallengeData.numericalPassword(value: passcode, timeout: data.autolockDeadline, attempts: nil) + } else { + data = PostboxAccessChallengeData.plaintextPassword(value: passcode, timeout: data.autolockDeadline, attempts: nil) + } + transaction.setAccessChallengeData(data) + }) |> deliverOnMainQueue).start(next: { _ in + }, error: { _ in + }, completed: { + popControllerImpl?() + }) } + pushControllerImpl?(setupController) }) }, changePasscodeTimeout: { let presentationData = context.sharedContext.currentPresentationData.with { $0 } @@ -408,38 +347,6 @@ func passcodeOptionsController(context: AccountContext) -> ViewController { return current.withUpdatedEnableBiometrics(value) }).start() }) - }, toggleSimplePasscode: { value in - var dismissImpl: (() -> Void)? - - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - - let legacyController = LegacyController(presentation: LegacyControllerPresentation.modal(animateIn: true), theme: presentationData.theme) - let controller = TGPasscodeEntryController(context: legacyController.context, style: TGPasscodeEntryControllerStyleDefault, mode: value ? TGPasscodeEntryControllerModeSetupSimple : TGPasscodeEntryControllerModeSetupComplex, cancelEnabled: true, allowTouchId: false, attemptData: nil, completion: { result in - if let result = result { - let challenge = value ? PostboxAccessChallengeData.numericalPassword(value: result, timeout: nil, attempts: nil) : PostboxAccessChallengeData.plaintextPassword(value: result, timeout: nil, attempts: nil) - let _ = (context.sharedContext.accountManager.transaction { transaction -> Void in - transaction.setAccessChallengeData(challenge) - updatePresentationPasscodeSettingsInternal(transaction: transaction, { current in - return current.withUpdatedAutolockTimeout(1 * 60 * 60) - }) - }).start() - - let _ = (passcodeOptionsDataPromise.get() |> take(1)).start(next: { [weak passcodeOptionsDataPromise] data in - passcodeOptionsDataPromise?.set(.single(data.withUpdatedAccessChallenge(challenge).withUpdatedPresentationSettings(data.presentationSettings.withUpdatedAutolockTimeout(1 * 60 * 60)))) - }) - - dismissImpl?() - } else { - dismissImpl?() - } - })! - legacyController.bind(controller: controller) - legacyController.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .portrait, compactSize: .portrait) - legacyController.statusBar.statusBarStyle = .White - presentControllerImpl?(legacyController, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - dismissImpl = { [weak legacyController] in - legacyController?.dismiss() - } }) let signal = combineLatest(context.sharedContext.presentationData, statePromise.get(), passcodeOptionsDataPromise.get()) |> deliverOnMainQueue @@ -462,6 +369,9 @@ func passcodeOptionsController(context: AccountContext) -> ViewController { pushControllerImpl = { [weak controller] c in (controller?.navigationController as? NavigationController)?.pushViewController(c) } + popControllerImpl = { [weak controller] in + let _ = (controller?.navigationController as? NavigationController)?.popViewController(animated: true) + } replaceTopControllerImpl = { [weak controller] c, animated in (controller?.navigationController as? NavigationController)?.replaceTopController(c, animated: animated) } @@ -477,7 +387,7 @@ public func passcodeOptionsAccessController(context: AccountContext, animateIn: |> map { challenge -> ViewController? in if case .none = challenge { let controller = PrivacyIntroController(context: context, mode: .passcode, proceedAction: { - let setupController = PasscodeSetupController(context: context, mode: .setup(.digits6)) + let setupController = PasscodeSetupController(context: context, mode: .setup(change: false, .digits6)) setupController.complete = { passcode, numerical in let _ = (context.sharedContext.accountManager.transaction({ transaction -> Void in var data = transaction.getAccessChallengeData() @@ -487,6 +397,8 @@ public func passcodeOptionsAccessController(context: AccountContext, animateIn: data = PostboxAccessChallengeData.plaintextPassword(value: passcode, timeout: data.autolockDeadline, attempts: nil) } transaction.setAccessChallengeData(data) + + updatePresentationPasscodeSettingsInternal(transaction: transaction, { $0.withUpdatedAutolockTimeout(1 * 60 * 60) }) }) |> deliverOnMainQueue).start(next: { _ in }, error: { _ in }, completed: { @@ -534,76 +446,17 @@ public func passcodeEntryController(context: AccountContext, animateIn: Bool = t completion(true) return nil } else { - var attemptData: TGPasscodeEntryAttemptData? - if let attempts = challenge.attempts { - attemptData = TGPasscodeEntryAttemptData(numberOfInvalidAttempts: Int(attempts.count), dateOfLastInvalidAttempt: Double(attempts.timestamp)) + let controller = PasscodeEntryController(context: context, challengeData: challenge, enableBiometrics: passcodeSettings?.enableBiometrics ?? false, arguments: PasscodeEntryControllerPresentationArguments(animated: animateIn, lockIconInitialFrame: { + return CGRect() + })) + controller.presentationCompleted = { [weak controller] in + controller?.requestBiometrics() } - var dismissImpl: (() -> Void)? - - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - - let legacyController = LegacyController(presentation: LegacyControllerPresentation.modal(animateIn: true), theme: presentationData.theme) - let mode: TGPasscodeEntryControllerMode - switch challenge { - case .none, .numericalPassword: - mode = TGPasscodeEntryControllerModeVerifySimple - case .plaintextPassword: - mode = TGPasscodeEntryControllerModeVerifyComplex + controller.completed = { [weak controller] in + controller?.dismiss(completion: nil) + completion(true) } - let controller = TGPasscodeEntryController(context: legacyController.context, style: TGPasscodeEntryControllerStyleDefault, mode: mode, cancelEnabled: true, allowTouchId: passcodeSettings?.enableBiometrics ?? false, attemptData: attemptData, completion: { value in - completion(value != nil) - dismissImpl?() - })! - if passcodeSettings?.enableBiometrics ?? false { - controller.touchIdCompletion = { - completion(true) - dismissImpl?() - } - } - controller.checkCurrentPasscode = { value in - if let value = value { - switch challenge { - case .none: - return true - case let .numericalPassword(code, _, _): - return value == code - case let .plaintextPassword(code, _, _): - return value == code - } - } else { - return false - } - } - controller.updateAttemptData = { attemptData in - let _ = context.sharedContext.accountManager.transaction({ transaction -> Void in - var attempts: AccessChallengeAttempts? - if let attemptData = attemptData { - attempts = AccessChallengeAttempts(count: Int32(attemptData.numberOfInvalidAttempts), timestamp: Int32(attemptData.dateOfLastInvalidAttempt)) - } - var data = transaction.getAccessChallengeData() - switch data { - case .none: - break - case let .numericalPassword(value, timeout, _): - data = .numericalPassword(value: value, timeout: timeout, attempts: attempts) - case let .plaintextPassword(value, timeout, _): - data = .plaintextPassword(value: value, timeout: timeout, attempts: attempts) - } - transaction.setAccessChallengeData(data) - }).start() - } - legacyController.presentationCompleted = { [weak controller] in - if passcodeSettings?.enableBiometrics ?? false { - controller?.refreshTouchId() - } - } - legacyController.bind(controller: controller) - legacyController.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .portrait, compactSize: .portrait) - legacyController.statusBar.statusBarStyle = .White - dismissImpl = { [weak legacyController] in - legacyController?.dismiss() - } - return legacyController + return controller } } } diff --git a/TelegramUI/PasscodeSetupController.swift b/TelegramUI/PasscodeSetupController.swift index 06f467991c..4e8eef296c 100644 --- a/TelegramUI/PasscodeSetupController.swift +++ b/TelegramUI/PasscodeSetupController.swift @@ -6,7 +6,7 @@ import SwiftSignalKit import Postbox enum PasscodeSetupControllerMode { - case setup(PasscodeEntryFieldType) + case setup(change: Bool, PasscodeEntryFieldType) case entry(PostboxAccessChallengeData) } @@ -34,6 +34,7 @@ final class PasscodeSetupController: ViewController { super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData)) + self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBar.style.style self.nextAction = UIBarButtonItem(title: self.presentationData.strings.Common_Next, style: .done, target: self, action: #selector(self.nextPressed)) @@ -50,7 +51,7 @@ final class PasscodeSetupController: ViewController { self.displayNodeDidLoad() self.controllerNode.selectPasscodeMode = { [weak self] in - guard let strongSelf = self, case let .setup(type) = strongSelf.mode else { + guard let strongSelf = self, case let .setup(change, type) = strongSelf.mode else { return } @@ -65,7 +66,7 @@ final class PasscodeSetupController: ViewController { } else { items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.PasscodeSettings_6DigitCode, action: { [weak self] in if let strongSelf = self { - strongSelf.mode = .setup(.digits6) + strongSelf.mode = .setup(change: change, .digits6) strongSelf.controllerNode.updateMode(strongSelf.mode) } dismissAction() @@ -75,7 +76,7 @@ final class PasscodeSetupController: ViewController { } else { items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.PasscodeSettings_4DigitCode, action: { if let strongSelf = self { - strongSelf.mode = .setup(.digits4) + strongSelf.mode = .setup(change: change, .digits4) strongSelf.controllerNode.updateMode(strongSelf.mode) } dismissAction() @@ -85,7 +86,7 @@ final class PasscodeSetupController: ViewController { } else { items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.PasscodeSettings_AlphanumericCode, action: { if let strongSelf = self { - strongSelf.mode = .setup(.alphanumeric) + strongSelf.mode = .setup(change: change, .alphanumeric) strongSelf.controllerNode.updateMode(strongSelf.mode) } dismissAction() @@ -130,6 +131,7 @@ final class PasscodeSetupController: ViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) + self.view.disablesInteractiveTransitionGestureRecognizer = true self.controllerNode.activateInput() } @@ -137,7 +139,7 @@ final class PasscodeSetupController: ViewController { override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { super.containerLayoutUpdated(layout, transition: transition) - self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: 0.0, transition: transition) + self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationHeight, transition: transition) } @objc func nextPressed() { diff --git a/TelegramUI/PasscodeSetupControllerNode.swift b/TelegramUI/PasscodeSetupControllerNode.swift index 52ad207c4f..9ccd620cf7 100644 --- a/TelegramUI/PasscodeSetupControllerNode.swift +++ b/TelegramUI/PasscodeSetupControllerNode.swift @@ -49,8 +49,9 @@ final class PasscodeSetupControllerNode: ASDisplayNode { private let hapticFeedback = HapticFeedback() - private var validLayout: ContainerViewLayout? - + private var validLayout: (ContainerViewLayout, CGFloat)? + private var maxBottomInset: CGFloat? + init(presentationData: PresentationData, mode: PasscodeSetupControllerMode) { self.presentationData = presentationData self.mode = mode @@ -103,8 +104,12 @@ final class PasscodeSetupControllerNode: ASDisplayNode { case .entry: self.modeButtonNode.isHidden = true text = self.presentationData.strings.EnterPasscode_EnterPasscode - case .setup: - text = self.presentationData.strings.EnterPasscode_EnterNewPasscodeNew + case let .setup(change, _): + if change { + text = self.presentationData.strings.EnterPasscode_EnterNewPasscodeChange + } else { + text = self.presentationData.strings.EnterPasscode_EnterNewPasscodeNew + } } self.titleNode.attributedText = NSAttributedString(string: text, font: Font.regular(17.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor) @@ -116,13 +121,22 @@ final class PasscodeSetupControllerNode: ASDisplayNode { } func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) { - self.validLayout = layout + self.validLayout = (layout, navigationBarHeight) - let insets = layout.insets(options: [.statusBar, .input]) + var insets = layout.insets(options: [.statusBar, .input]) + if let maxBottomInset = self.maxBottomInset { + if maxBottomInset > insets.bottom { + insets.bottom = maxBottomInset + } else { + self.maxBottomInset = insets.bottom + } + } else { + self.maxBottomInset = insets.bottom + } self.wrapperNode.frame = CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: layout.size.height) - let passcodeLayout = PasscodeLayout(layout: layout, titleOffset: 0.0, subtitleOffset: 0.0, inputFieldOffset: floor(insets.top + navigationBarHeight + (layout.size.height - navigationBarHeight - insets.top - insets.bottom - 38.0) / 2.0)) + let passcodeLayout = PasscodeLayout(layout: layout, titleOffset: 0.0, subtitleOffset: 0.0, inputFieldOffset: floor(insets.top + navigationBarHeight + (layout.size.height - navigationBarHeight - insets.top - insets.bottom - 24.0) / 2.0)) let inputFieldFrame = self.inputFieldNode.updateLayout(layout: passcodeLayout, transition: transition) transition.updateFrame(node: self.inputFieldNode, frame: CGRect(origin: CGPoint(), size: layout.size)) @@ -138,7 +152,7 @@ final class PasscodeSetupControllerNode: ASDisplayNode { self.mode = mode self.inputFieldNode.reset() - if case let .setup(type) = mode { + if case let .setup(_, type) = mode { self.inputFieldNode.updateFieldType(type, animated: true) let fieldBackgroundAlpha: CGFloat @@ -170,7 +184,7 @@ final class PasscodeSetupControllerNode: ASDisplayNode { if let previousPasscode = self.previousPasscode { if self.currentPasscode == previousPasscode { var numerical = false - if case let .setup(type) = mode { + if case let .setup(_, type) = mode { if case .alphanumeric = type { } else { numerical = true @@ -196,7 +210,7 @@ final class PasscodeSetupControllerNode: ASDisplayNode { self.modeButtonNode.isHidden = true if let validLayout = self.validLayout { - self.containerLayoutUpdated(validLayout, navigationBarHeight: 0.0, transition: .immediate) + self.containerLayoutUpdated(validLayout.0, navigationBarHeight: validLayout.1, transition: .immediate) } } }