This commit is contained in:
Isaac
2025-12-02 19:30:48 +08:00
parent 0ac2602f7f
commit 2e279e8fd3
7 changed files with 68 additions and 3 deletions

View File

@@ -1475,6 +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 navigateToCurrentCall()
var hasOngoingCall: ValuePromise<Bool> { get }

View File

@@ -137,6 +137,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
private let dismissAutoarchiveDisposable = MetaDisposable()
private var didSuggestAutoarchive = false
private var didSuggestLoginEmailSetup = false
private var didSuggestLoginPasskeySetup = false
private var presentationData: PresentationData
private let presentationDataValue = Promise<PresentationData>()
@@ -2586,6 +2587,35 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
return
}
if values.contains(.setupPasskey) {
if strongSelf.didSuggestLoginPasskeySetup {
return
}
strongSelf.didSuggestLoginPasskeySetup = true
let _ = (context.engine.notices.getServerProvidedSuggestions(reload: true)
|> deliverOnMainQueue).start(next: { [weak strongSelf] currentValues in
guard let strongSelf, currentValues.contains(.setupPasskey) else {
return
}
if let navigationController = strongSelf.navigationController as? NavigationController {
let controller = strongSelf.context.sharedContext.makePasskeySetupController(context: strongSelf.context, displaySkip: true, navigationController: navigationController, completion: {
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupPasskey.id).startStandalone()
}, 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)
}
})
return
}
if strongSelf.didSuggestAutoarchive {
return
}

View File

@@ -20,6 +20,7 @@ public enum ServerProvidedSuggestion: Equatable {
case setupPhoto
case setupLoginEmail
case setupLoginEmailBlocking
case setupPasskey
case link(id: String, url: String, title: ServerSuggestionInfo.Item.Text, subtitle: ServerSuggestionInfo.Item.Text)
init?(string: String) {
@@ -56,6 +57,8 @@ public enum ServerProvidedSuggestion: Equatable {
self = .setupLoginEmail
case "SETUP_LOGIN_EMAIL_NOSKIP":
self = .setupLoginEmailBlocking
case "SETUP_PASSKEY":
self = .setupPasskey
default:
return nil
}
@@ -95,6 +98,8 @@ public enum ServerProvidedSuggestion: Equatable {
return "SETUP_LOGIN_EMAIL"
case .setupLoginEmailBlocking:
return "SETUP_LOGIN_EMAIL_NOSKIP"
case .setupPasskey:
return "SETUP_PASSKEY"
case let .link(id, _, _, _):
return id
}

View File

@@ -498,6 +498,7 @@ swift_library(
"//submodules/TelegramUI/Components/AttachmentFileController",
"//submodules/TelegramUI/Components/Contacts/NewContactScreen",
"//submodules/TelegramUI/Components/Chat/ChatSendAsContextMenu",
"//submodules/TelegramUI/Components/Settings/PasskeysScreen",
] + select({
"@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets,
"//build-system:ios_sim_arm64": [],

View File

@@ -19,17 +19,26 @@ final class PasskeysScreenComponent: Component {
typealias EnvironmentType = ViewControllerComponentContainer.Environment
let context: AccountContext
let displaySkip: Bool
let initialPasskeysData: [TelegramPasskey]?
let passkeysDataUpdated: ([TelegramPasskey]) -> Void
let completion: () -> Void
let cancel: () -> Void
init(
context: AccountContext,
displaySkip: Bool,
initialPasskeysData: [TelegramPasskey]?,
passkeysDataUpdated: @escaping ([TelegramPasskey]) -> Void
passkeysDataUpdated: @escaping ([TelegramPasskey]) -> Void,
completion: @escaping () -> Void,
cancel: @escaping () -> Void
) {
self.context = context
self.displaySkip = displaySkip
self.initialPasskeysData = initialPasskeysData
self.passkeysDataUpdated = passkeysDataUpdated
self.completion = completion
self.cancel = cancel
}
static func ==(lhs: PasskeysScreenComponent, rhs: PasskeysScreenComponent) -> Bool {
@@ -353,10 +362,10 @@ final class PasskeysScreenComponent: Component {
public final class PasskeysScreen: ViewControllerComponentContainer {
private let context: AccountContext
public init(context: AccountContext, initialPasskeysData: [TelegramPasskey]?, passkeysDataUpdated: @escaping ([TelegramPasskey]) -> Void) async {
public init(context: AccountContext, displaySkip: Bool, initialPasskeysData: [TelegramPasskey]?, passkeysDataUpdated: @escaping ([TelegramPasskey]) -> Void, completion: @escaping () -> Void, cancel: @escaping () -> Void) async {
self.context = context
super.init(context: context, component: PasskeysScreenComponent(context: context, initialPasskeysData: initialPasskeysData, passkeysDataUpdated: passkeysDataUpdated), navigationBarAppearance: .transparent)
super.init(context: context, component: PasskeysScreenComponent(context: context, displaySkip: displaySkip, initialPasskeysData: initialPasskeysData, passkeysDataUpdated: passkeysDataUpdated), navigationBarAppearance: .transparent)
}
required public init(coder aDecoder: NSCoder) {

View File

@@ -14,17 +14,20 @@ final class PasskeysScreenIntroComponent: Component {
let context: AccountContext
let theme: PresentationTheme
let insets: UIEdgeInsets
let displaySkip: Bool
let createPasskeyAction: () -> Void
init(
context: AccountContext,
theme: PresentationTheme,
insets: UIEdgeInsets,
displaySkip: Bool,
createPasskeyAction: @escaping () -> Void
) {
self.context = context
self.theme = theme
self.insets = insets
self.displaySkip = displaySkip
self.createPasskeyAction = createPasskeyAction
}
@@ -38,6 +41,9 @@ final class PasskeysScreenIntroComponent: Component {
if lhs.insets != rhs.insets {
return false
}
if lhs.displaySkip != rhs.displaySkip {
return false
}
return true
}
@@ -64,6 +70,7 @@ final class PasskeysScreenIntroComponent: Component {
private let title = ComponentView<Empty>()
private let subtitle = ComponentView<Empty>()
private let actionButton = ComponentView<Empty>()
private var skipButton: ComponentView<Empty>?
private var items: [Item] = []
@@ -292,6 +299,13 @@ final class PasskeysScreenIntroComponent: Component {
environment: {},
containerSize: CGSize(width: availableSize.width - buttonInsets.left - buttonInsets.right, height: 52.0)
)
if component.displaySkip {
let skipButton: ComponentView<Empty>
} 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)

View File

@@ -90,6 +90,7 @@ import ForumCreateTopicScreen
import GlassBackgroundComponent
import AttachmentFileController
import NewContactScreen
import PasskeysScreen
private final class AccountUserInterfaceInUseContext {
let subscribers = Bag<(Bool) -> Void>()
@@ -4063,6 +4064,10 @@ public final class SharedAccountContextImpl: SharedAccountContext {
public func makeLoginEmailSetupController(context: AccountContext, blocking: Bool, emailPattern: String?, canAutoDismissIfNeeded: Bool, navigationController: NavigationController?, completion: @escaping () -> Void, dismiss: @escaping () -> Void) -> ViewController {
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 {
return PasskeysScreen(context: context, displaySkip: displaySkip, initialPasskeysData: nil, passkeysDataUpdated: { _ in }, completion: completion, cancel: dismiss)
}
}
private func peerInfoControllerImpl(context: AccountContext, updatedPresentationData: (PresentationData, Signal<PresentationData, NoError>)?, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, requestsContext: PeerInvitationImportersContext? = nil) -> ViewController? {