This commit is contained in:
Isaac 2025-12-02 19:59:39 +08:00
parent 2e279e8fd3
commit 62d29ee551
6 changed files with 84 additions and 13 deletions

View file

@ -1475,7 +1475,7 @@ public protocol SharedAccountContext: AnyObject {
func makeNewContactScreen(context: AccountContext, peer: EnginePeer?, phoneNumber: String?, shareViaException: Bool, completion: @escaping (EnginePeer?, DeviceContactStableId?, DeviceContactExtendedData?) -> Void) -> ViewController
func makeLoginEmailSetupController(context: AccountContext, blocking: Bool, emailPattern: String?, canAutoDismissIfNeeded: Bool, navigationController: NavigationController?, completion: @escaping () -> Void, dismiss: @escaping () -> Void) -> ViewController
public func makePasskeySetupController(context: AccountContext, displaySkip: Bool, navigationController: NavigationController?, completion: @escaping () -> Void, dismiss: completion: @escaping () -> Void) -> ViewController
func makePasskeySetupController(context: AccountContext, displaySkip: Bool, navigationController: NavigationController?, completion: @escaping () -> Void, dismiss: @escaping () -> Void) -> ViewController
func navigateToCurrentCall()
var hasOngoingCall: ValuePromise<Bool> { get }

View file

@ -2604,11 +2604,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
}, dismiss: {
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupPasskey.id).startStandalone()
})
if let layout = strongSelf.validLayout, layout.metrics.isTablet {
controller.navigationPresentation = .standaloneFlatModal
} else {
controller.navigationPresentation = .flatModal
}
navigationController.pushViewController(controller)
}
})

View file

@ -1268,9 +1268,9 @@ public func privacyAndSecurityController(
}, openPasskeys: {
Task { @MainActor in
let initialPasskeysData = await (passkeysDataValue.get() |> take(1)).get()
let passkeysScreen = await PasskeysScreen(context: context, initialPasskeysData: initialPasskeysData, passkeysDataUpdated: { passkeysData in
let passkeysScreen = PasskeysScreen(context: context, displaySkip: false, initialPasskeysData: initialPasskeysData, passkeysDataUpdated: { passkeysData in
passkeysDataValue.set(.single(passkeysData))
})
}, completion: {}, cancel: {})
pushControllerImpl?(passkeysScreen, true)
}
}, openActiveSessions: {

View file

@ -48,6 +48,7 @@ final class PasskeysScreenComponent: Component {
class View: UIView, ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding {
private var intro: ComponentView<Empty>?
private var list: ComponentView<Empty>?
private var activityIndicator: UIActivityIndicatorView?
private var component: PasskeysScreenComponent?
private var environment: EnvironmentType?
@ -168,6 +169,8 @@ final class PasskeysScreenComponent: Component {
authController.delegate = self
authController.presentationContextProvider = self
authController.performRequests()
component.completion()
}
}
}
@ -264,11 +267,19 @@ final class PasskeysScreenComponent: Component {
context: component.context,
theme: environment.theme,
insets: UIEdgeInsets(top: environment.statusBarHeight + environment.navigationHeight, left: 0.0, bottom: environment.safeInsets.bottom, right: 0.0),
displaySkip: component.displaySkip,
createPasskeyAction: { [weak self] in
guard let self else {
return
}
self.createPasskey()
},
skipAction: { [weak self] in
guard let self, let component = self.component else {
return
}
component.cancel()
self.environment?.controller()?.dismiss()
}
)),
environment: {},
@ -346,6 +357,27 @@ final class PasskeysScreenComponent: Component {
}
}
if self.passkeysData == nil {
let activityIndicator: UIActivityIndicatorView
if let current = self.activityIndicator {
activityIndicator = current
} else {
activityIndicator = UIActivityIndicatorView(style: .large)
self.activityIndicator = activityIndicator
self.addSubview(activityIndicator)
}
activityIndicator.tintColor = environment.theme.list.itemPrimaryTextColor
let indicatorSize = activityIndicator.bounds.size
activityIndicator.frame = CGRect(origin: CGPoint(x: floor((availableSize.width - indicatorSize.width) / 2.0), y: floor((availableSize.height - indicatorSize.height) / 2.0)), size: indicatorSize)
if !activityIndicator.isAnimating {
activityIndicator.startAnimating()
}
} else if let activityIndicator = self.activityIndicator {
self.activityIndicator = nil
activityIndicator.removeFromSuperview()
}
return availableSize
}
}
@ -362,10 +394,10 @@ final class PasskeysScreenComponent: Component {
public final class PasskeysScreen: ViewControllerComponentContainer {
private let context: AccountContext
public init(context: AccountContext, displaySkip: Bool, initialPasskeysData: [TelegramPasskey]?, passkeysDataUpdated: @escaping ([TelegramPasskey]) -> Void, completion: @escaping () -> Void, cancel: @escaping () -> Void) async {
public init(context: AccountContext, displaySkip: Bool, initialPasskeysData: [TelegramPasskey]?, passkeysDataUpdated: @escaping ([TelegramPasskey]) -> Void, completion: @escaping () -> Void, cancel: @escaping () -> Void) {
self.context = context
super.init(context: context, component: PasskeysScreenComponent(context: context, displaySkip: displaySkip, initialPasskeysData: initialPasskeysData, passkeysDataUpdated: passkeysDataUpdated), navigationBarAppearance: .transparent)
super.init(context: context, component: PasskeysScreenComponent(context: context, displaySkip: displaySkip, initialPasskeysData: initialPasskeysData, passkeysDataUpdated: passkeysDataUpdated, completion: completion, cancel: cancel), navigationBarAppearance: .transparent)
}
required public init(coder aDecoder: NSCoder) {

View file

@ -16,19 +16,22 @@ final class PasskeysScreenIntroComponent: Component {
let insets: UIEdgeInsets
let displaySkip: Bool
let createPasskeyAction: () -> Void
let skipAction: () -> Void
init(
context: AccountContext,
theme: PresentationTheme,
insets: UIEdgeInsets,
displaySkip: Bool,
createPasskeyAction: @escaping () -> Void
createPasskeyAction: @escaping () -> Void,
skipAction: @escaping () -> Void
) {
self.context = context
self.theme = theme
self.insets = insets
self.displaySkip = displaySkip
self.createPasskeyAction = createPasskeyAction
self.skipAction = skipAction
}
static func ==(lhs: PasskeysScreenIntroComponent, rhs: PasskeysScreenIntroComponent) -> Bool {
@ -300,14 +303,55 @@ final class PasskeysScreenIntroComponent: Component {
containerSize: CGSize(width: availableSize.width - buttonInsets.left - buttonInsets.right, height: 52.0)
)
var skipButtonSize: CGSize?
if component.displaySkip {
let skipButton: ComponentView<Empty>
if let current = self.skipButton {
skipButton = current
} else {
skipButton = ComponentView()
self.skipButton = skipButton
}
//TODO:localize
skipButtonSize = skipButton.update(
transition: transition,
component: AnyComponent(ButtonComponent(
background: ButtonComponent.Background(
style: .glass,
color: component.theme.chatList.unreadBadgeInactiveBackgroundColor,
foreground: component.theme.list.itemCheckColors.foregroundColor,
pressedColor: component.theme.chatList.unreadBadgeInactiveBackgroundColor.withMultipliedAlpha(0.9),
cornerRadius: 52.0 * 0.5
),
content: AnyComponentWithIdentity(
id: AnyHashable(0),
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: "Skip", font: Font.semibold(17.0), textColor: component.theme.list.itemCheckColors.foregroundColor))))
),
action: { [weak self] in
guard let self, let component = self.component else {
return
}
component.skipAction()
}
)),
environment: {},
containerSize: CGSize(width: availableSize.width - buttonInsets.left - buttonInsets.right, height: 52.0)
)
} else if let skipButton = self.skipButton {
self.skipButton = nil
skipButton.view?.removeFromSuperview()
}
let buttonFrame = CGRect(origin: CGPoint(x: buttonInsets.left, y: availableSize.height - buttonInsets.bottom - actionButtonSize.height), size: actionButtonSize)
var buttonFrame = CGRect(origin: CGPoint(x: buttonInsets.left, y: availableSize.height - buttonInsets.bottom - actionButtonSize.height), size: actionButtonSize)
if let skipButtonSize, let skipButtonView = self.skipButton?.view {
let skipButtonFrame = buttonFrame
buttonFrame = buttonFrame.offsetBy(dx: 0.0, dy: -8.0 - skipButtonSize.height)
if skipButtonView.superview == nil {
self.addSubview(skipButtonView)
}
transition.setFrame(view: skipButtonView, frame: skipButtonFrame)
}
if let actionButtonView = self.actionButton.view {
if actionButtonView.superview == nil {

View file

@ -4065,7 +4065,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
return loginEmailSetupController(context: context, blocking: blocking, emailPattern: emailPattern, canAutoDismissIfNeeded: canAutoDismissIfNeeded, navigationController: navigationController, completion: completion, dismiss: dismiss)
}
public func makePasskeySetupController(context: AccountContext, displaySkip: Bool, navigationController: NavigationController?, completion: @escaping () -> Void, dismiss: completion: @escaping () -> Void) -> ViewController {
public func makePasskeySetupController(context: AccountContext, displaySkip: Bool, navigationController: NavigationController?, completion: @escaping () -> Void, dismiss: @escaping () -> Void) -> ViewController {
return PasskeysScreen(context: context, displaySkip: displaySkip, initialPasskeysData: nil, passkeysDataUpdated: { _ in }, completion: completion, cancel: dismiss)
}
}