import Foundation import SwiftSignalKit import UIKit import Postbox import TelegramCore import Display public final class TelegramApplicationOpenUrlCompletion { public let completion: (Bool) -> Void public init(completion: @escaping (Bool) -> Void) { self.completion = completion } } public final class TelegramApplicationBindings { public let isMainApp: Bool public let containerPath: String public let appSpecificScheme: String public let openUrl: (String) -> Void public let openUniversalUrl: (String, TelegramApplicationOpenUrlCompletion) -> Void public let canOpenUrl: (String) -> Bool public let getTopWindow: () -> UIWindow? public let displayNotification: (String) -> Void public let applicationInForeground: Signal public let applicationIsActive: Signal public let clearMessageNotifications: ([MessageId]) -> Void public let pushIdleTimerExtension: () -> Disposable public let openSettings: () -> Void public let openAppStorePage: () -> Void public let registerForNotifications: (@escaping (Bool) -> Void) -> Void public let requestSiriAuthorization: (@escaping (Bool) -> Void) -> Void public let siriAuthorization: () -> AccessType public let getWindowHost: () -> WindowHost? public let presentNativeController: (UIViewController) -> Void public let dismissNativeController: () -> Void public let getAvailableAlternateIcons: () -> [PresentationAppIcon] public let getAlternateIconName: () -> String? public let requestSetAlternateIconName: (String?, @escaping (Bool) -> Void) -> Void public init(isMainApp: Bool, containerPath: String, appSpecificScheme: String, openUrl: @escaping (String) -> Void, openUniversalUrl: @escaping (String, TelegramApplicationOpenUrlCompletion) -> Void, canOpenUrl: @escaping (String) -> Bool, getTopWindow: @escaping () -> UIWindow?, displayNotification: @escaping (String) -> Void, applicationInForeground: Signal, applicationIsActive: Signal, clearMessageNotifications: @escaping ([MessageId]) -> Void, pushIdleTimerExtension: @escaping () -> Disposable, openSettings: @escaping () -> Void, openAppStorePage: @escaping () -> Void, registerForNotifications: @escaping (@escaping (Bool) -> Void) -> Void, requestSiriAuthorization: @escaping (@escaping (Bool) -> Void) -> Void, siriAuthorization: @escaping () -> AccessType, getWindowHost: @escaping () -> WindowHost?, presentNativeController: @escaping (UIViewController) -> Void, dismissNativeController: @escaping () -> Void, getAvailableAlternateIcons: @escaping () -> [PresentationAppIcon], getAlternateIconName: @escaping () -> String?, requestSetAlternateIconName: @escaping (String?, @escaping (Bool) -> Void) -> Void) { self.isMainApp = isMainApp self.containerPath = containerPath self.appSpecificScheme = appSpecificScheme self.openUrl = openUrl self.openUniversalUrl = openUniversalUrl self.canOpenUrl = canOpenUrl self.getTopWindow = getTopWindow self.displayNotification = displayNotification self.applicationInForeground = applicationInForeground self.applicationIsActive = applicationIsActive self.clearMessageNotifications = clearMessageNotifications self.pushIdleTimerExtension = pushIdleTimerExtension self.openSettings = openSettings self.openAppStorePage = openAppStorePage self.registerForNotifications = registerForNotifications self.requestSiriAuthorization = requestSiriAuthorization self.siriAuthorization = siriAuthorization self.presentNativeController = presentNativeController self.dismissNativeController = dismissNativeController self.getWindowHost = getWindowHost self.getAvailableAlternateIcons = getAvailableAlternateIcons self.getAlternateIconName = getAlternateIconName self.requestSetAlternateIconName = requestSetAlternateIconName } } public final class AccountContext { public let sharedContext: SharedAccountContext public let account: Account public let fetchManager: FetchManager private let prefetchManager: PrefetchManager? public var keyShortcutsController: KeyShortcutsController? let downloadedMediaStoreManager: DownloadedMediaStoreManager public let liveLocationManager: LiveLocationManager? let wallpaperUploadManager: WallpaperUploadManager? let peerChannelMemberCategoriesContextsManager = PeerChannelMemberCategoriesContextsManager() public let currentLimitsConfiguration: Atomic private let _limitsConfiguration = Promise() public var limitsConfiguration: Signal { return self._limitsConfiguration.get() } public var watchManager: WatchManager? private var storedPassword: (String, CFAbsoluteTime, SwiftSignalKit.Timer)? private var limitsConfigurationDisposable: Disposable? public init(sharedContext: SharedAccountContext, account: Account, limitsConfiguration: LimitsConfiguration) { self.sharedContext = sharedContext self.account = account self.downloadedMediaStoreManager = DownloadedMediaStoreManager(postbox: account.postbox, accountManager: sharedContext.accountManager) if let locationManager = self.sharedContext.locationManager { self.liveLocationManager = LiveLocationManager(postbox: account.postbox, network: account.network, accountPeerId: account.peerId, viewTracker: account.viewTracker, stateManager: account.stateManager, locationManager: locationManager, inForeground: self.sharedContext.applicationBindings.applicationInForeground) } else { self.liveLocationManager = nil } self.fetchManager = FetchManager(postbox: account.postbox, storeManager: self.downloadedMediaStoreManager) if sharedContext.applicationBindings.isMainApp { self.prefetchManager = PrefetchManager(sharedContext: sharedContext, account: account, fetchManager: fetchManager) self.wallpaperUploadManager = WallpaperUploadManager(sharedContext: sharedContext, account: account, presentationData: sharedContext.presentationData) } else { self.prefetchManager = nil self.wallpaperUploadManager = nil } let updatedLimitsConfiguration = account.postbox.preferencesView(keys: [PreferencesKeys.limitsConfiguration]) |> map { preferences -> LimitsConfiguration in return preferences.values[PreferencesKeys.limitsConfiguration] as? LimitsConfiguration ?? LimitsConfiguration.defaultValue } self.currentLimitsConfiguration = Atomic(value: limitsConfiguration) self._limitsConfiguration.set(.single(limitsConfiguration) |> then(updatedLimitsConfiguration)) let currentLimitsConfiguration = self.currentLimitsConfiguration self.limitsConfigurationDisposable = (self._limitsConfiguration.get() |> deliverOnMainQueue).start(next: { value in let _ = currentLimitsConfiguration.swap(value) }) } deinit { self.limitsConfigurationDisposable?.dispose() } public func storeSecureIdPassword(password: String) { self.storedPassword?.2.invalidate() let timer = SwiftSignalKit.Timer(timeout: 1.0 * 60.0 * 60.0, repeat: false, completion: { [weak self] in self?.storedPassword = nil }, queue: Queue.mainQueue()) self.storedPassword = (password, CFAbsoluteTimeGetCurrent(), timer) timer.start() } public func getStoredSecureIdPassword() -> String? { if let (password, timestamp, timer) = self.storedPassword { if CFAbsoluteTimeGetCurrent() > timestamp + 1.0 * 60.0 * 60.0 { timer.invalidate() self.storedPassword = nil } return password } else { return nil } } }