import UIKit import Display import SwiftSignalKit import TelegramCore import TelegramPresentationData import ItemListUI import AccountContext private final class BotSettingsArguments { let context: AccountContext let updateBiometryAccess: (Bool) -> Void init( context: AccountContext, updateBiometryAccess: @escaping (Bool) -> Void ) { self.context = context self.updateBiometryAccess = updateBiometryAccess } } private enum BotSettingsSection: Int32 { case settings } private enum BotSettingsEntry: ItemListNodeEntry { case biometryAccess(value: Bool) var section: ItemListSectionId { switch self { case .biometryAccess: return BotSettingsSection.settings.rawValue } } var stableId: Int { switch self { case .biometryAccess: return 0 } } static func ==(lhs: BotSettingsEntry, rhs: BotSettingsEntry) -> Bool { switch lhs { case let .biometryAccess(value): if case .biometryAccess(value) = rhs { return true } else { return false } } } static func <(lhs: BotSettingsEntry, rhs: BotSettingsEntry) -> Bool { return lhs.stableId < rhs.stableId } func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem { let arguments = arguments as! BotSettingsArguments switch self { case let .biometryAccess(value): return ItemListSwitchItem( presentationData: presentationData, title: presentationData.strings.Settings_BotSettings_Biometry, value: value, sectionId: self.section, style: .blocks, updated: { value in arguments.updateBiometryAccess(value) } ) } } } private struct BotSettingsState: Equatable { init() { } } private func botSettingsEntries( presentationData: PresentationData, peer: EnginePeer?, biometricsState: TelegramBotBiometricsState? ) -> [BotSettingsEntry] { var entries: [BotSettingsEntry] = [] if let biometricsState { entries.append(.biometryAccess(value: biometricsState.accessGranted)) } return entries } public func botSettingsScreen(context: AccountContext, peerId: EnginePeer.Id) -> ViewController { let initialState = BotSettingsState() let statePromise = ValuePromise(initialState, ignoreRepeated: true) let stateValue = Atomic(value: initialState) let updateState: ((BotSettingsState) -> BotSettingsState) -> Void = { f in statePromise.set(stateValue.modify { f($0) }) } var pushControllerImpl: ((ViewController) -> Void)? let _ = pushControllerImpl let _ = updateState let actionsDisposable = DisposableSet() let arguments = BotSettingsArguments( context: context, updateBiometryAccess: { value in context.engine.peers.updateBotBiometricsState(peerId: peerId, update: { state in var state = state ?? TelegramBotBiometricsState.create() state.accessGranted = value return state }) } ) let data = context.engine.data.subscribe( TelegramEngine.EngineData.Item.Peer.Peer(id: peerId), TelegramEngine.EngineData.Item.Peer.BotBiometricsState(id: peerId) ) let signal = combineLatest( context.sharedContext.presentationData, statePromise.get(), data ) |> deliverOnMainQueue |> map { presentationData, state, data -> (ItemListControllerState, (ItemListNodeState, Any)) in let (peer, biometricsState) = data let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(peer?.compactDisplayTitle ?? ""), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false) let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: botSettingsEntries(presentationData: presentationData, peer: peer, biometricsState: biometricsState), style: .blocks, animateChanges: true) return (controllerState, (listState, arguments)) } |> afterDisposed { actionsDisposable.dispose() } let controller = ItemListController(context: context, state: signal) pushControllerImpl = { [weak controller] c in (controller?.navigationController as? NavigationController)?.pushViewController(c) } return controller }