diff --git a/Telegram-iOS/AppDelegate.swift b/Telegram-iOS/AppDelegate.swift index 125df21817..2f30bb5667 100644 --- a/Telegram-iOS/AppDelegate.swift +++ b/Telegram-iOS/AppDelegate.swift @@ -120,7 +120,7 @@ private enum QueuedWakeup: Int32 { case backgroundLocation } -private final class SharedApplicationContext { +final class SharedApplicationContext { let sharedContext: SharedAccountContext let notificationManager: SharedNotificationManager let wakeupManager: SharedWakeupManager @@ -571,125 +571,131 @@ private final class SharedApplicationContext { self.window?.rootViewController?.dismiss(animated: true, completion: nil) }) - // Move back to signal - let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata") - let upgradeSemaphore = DispatchSemaphore(value: 0) - let _ = upgradedAccounts(accountManager: accountManager, rootPath: rootPath).start(completed: { - upgradeSemaphore.signal() - }) - upgradeSemaphore.wait() - - var initialPresentationDataAndSettings: InitialPresentationDataAndSettings? - let semaphore = DispatchSemaphore(value: 0) - let _ = currentPresentationDataAndSettings(accountManager: accountManager).start(next: { value in - initialPresentationDataAndSettings = value - semaphore.signal() - }) - semaphore.wait() - - let legacyBasePath = appGroupUrl.path - let legacyCache = LegacyCache(path: legacyBasePath + "/Caches") - - var setPresentationCall: ((PresentationCall?) -> Void)? - let sharedContext = SharedAccountContext(mainWindow: self.mainWindow, basePath: rootPath, accountManager: accountManager, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: networkArguments, rootPath: rootPath, legacyBasePath: legacyBasePath, legacyCache: legacyCache, apsNotificationToken: self.notificationTokenPromise.get() |> map(Optional.init), voipNotificationToken: self.voipTokenPromise.get() |> map(Optional.init), setNotificationCall: { call in - setPresentationCall?(call) - }, navigateToChat: { accountId, peerId, messageId in - self.openChatWhenReady(accountId: accountId, peerId: peerId, messageId: messageId) - }) - - let rawAccounts = sharedContext.activeAccounts - |> map { _, accounts, _ -> [Account] in - return accounts.map({ $0.1 }) + let accountManagerSignal = Signal { subscriber in + let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata") + return upgradedAccounts(accountManager: accountManager, rootPath: rootPath).start(completed: { + subscriber.putNext(accountManager) + subscriber.putCompletion() + }) + return EmptyDisposable } - let _ = (sharedAccountInfos(accountManager: sharedContext.accountManager, accounts: rawAccounts) - |> deliverOn(Queue())).start(next: { infos in - storeAccountsData(rootPath: rootPath, accounts: infos) - }) - sharedContext.presentGlobalController = { [weak self] c, a in - guard let strongSelf = self else { - return + let sharedContextSignal = accountManagerSignal + |> deliverOnMainQueue + |> mapToSignal { accountManager -> Signal<(SharedApplicationContext, LoggingSettings), NoError> in + var initialPresentationDataAndSettings: InitialPresentationDataAndSettings? + let semaphore = DispatchSemaphore(value: 0) + let _ = currentPresentationDataAndSettings(accountManager: accountManager).start(next: { value in + initialPresentationDataAndSettings = value + semaphore.signal() + }) + semaphore.wait() + + let legacyBasePath = appGroupUrl.path + let legacyCache = LegacyCache(path: legacyBasePath + "/Caches") + + var setPresentationCall: ((PresentationCall?) -> Void)? + let sharedContext = SharedAccountContext(mainWindow: self.mainWindow, basePath: rootPath, accountManager: accountManager, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: networkArguments, rootPath: rootPath, legacyBasePath: legacyBasePath, legacyCache: legacyCache, apsNotificationToken: self.notificationTokenPromise.get() |> map(Optional.init), voipNotificationToken: self.voipTokenPromise.get() |> map(Optional.init), setNotificationCall: { call in + setPresentationCall?(call) + }, navigateToChat: { accountId, peerId, messageId in + self.openChatWhenReady(accountId: accountId, peerId: peerId, messageId: messageId) + }) + + let rawAccounts = sharedContext.activeAccounts + |> map { _, accounts, _ -> [Account] in + return accounts.map({ $0.1 }) } - strongSelf.mainWindow.present(c, on: .root) - } - sharedContext.presentCrossfadeController = { [weak self] in - guard let strongSelf = self else { - return - } - var exists = false - strongSelf.mainWindow.forEachViewController { controller in - if controller is ThemeSettingsCrossfadeController { - exists = true + let _ = (sharedAccountInfos(accountManager: sharedContext.accountManager, accounts: rawAccounts) + |> deliverOn(Queue())).start(next: { infos in + storeAccountsData(rootPath: rootPath, accounts: infos) + }) + + sharedContext.presentGlobalController = { [weak self] c, a in + guard let strongSelf = self else { + return + } + strongSelf.mainWindow.present(c, on: .root) + } + sharedContext.presentCrossfadeController = { [weak self] in + guard let strongSelf = self else { + return + } + var exists = false + strongSelf.mainWindow.forEachViewController { controller in + if controller is ThemeSettingsCrossfadeController { + exists = true + } + return true + } + + if !exists { + strongSelf.mainWindow.present(ThemeSettingsCrossfadeController(), on: .root) } - return true } - if !exists { - strongSelf.mainWindow.present(ThemeSettingsCrossfadeController(), on: .root) - } - } - - let notificationManager = SharedNotificationManager(episodeId: self.episodeId, application: application, clearNotificationsManager: clearNotificationsManager, inForeground: applicationBindings.applicationInForeground, accounts: sharedContext.activeAccounts |> map { primary, accounts, _ in accounts.map({ ($0.1, $0.1.id == primary?.id) }) }, pollLiveLocationOnce: { accountId in - let _ = (self.context.get() - |> filter { - return $0 != nil - } - |> take(1) - |> deliverOnMainQueue).start(next: { context in - if let context = context, context.context.account.id == accountId { - context.context.liveLocationManager?.pollOnce() + let notificationManager = SharedNotificationManager(episodeId: self.episodeId, application: application, clearNotificationsManager: clearNotificationsManager, inForeground: applicationBindings.applicationInForeground, accounts: sharedContext.activeAccounts |> map { primary, accounts, _ in accounts.map({ ($0.1, $0.1.id == primary?.id) }) }, pollLiveLocationOnce: { accountId in + let _ = (self.context.get() + |> filter { + return $0 != nil } + |> take(1) + |> deliverOnMainQueue).start(next: { context in + if let context = context, context.context.account.id == accountId { + context.context.liveLocationManager?.pollOnce() + } + }) }) - }) - setPresentationCall = { call in - notificationManager.setNotificationCall(call, strings: sharedContext.currentPresentationData.with({ $0 }).strings) - } - let liveLocationPolling = self.context.get() - |> mapToSignal { context -> Signal in - if let context = context, let liveLocationManager = context.context.liveLocationManager { - let accountId = context.context.account.id - return liveLocationManager.isPolling - |> distinctUntilChanged - |> map { value -> AccountRecordId? in - if value { - return accountId - } else { - return nil + setPresentationCall = { call in + notificationManager.setNotificationCall(call, strings: sharedContext.currentPresentationData.with({ $0 }).strings) + } + let liveLocationPolling = self.context.get() + |> mapToSignal { context -> Signal in + if let context = context, let liveLocationManager = context.context.liveLocationManager { + let accountId = context.context.account.id + return liveLocationManager.isPolling + |> distinctUntilChanged + |> map { value -> AccountRecordId? in + if value { + return accountId + } else { + return nil + } } + } else { + return .single(nil) } - } else { - return .single(nil) + } + let watchTasks = self.context.get() + |> mapToSignal { context -> Signal in + if let context = context, let watchManager = context.context.watchManager { + let accountId = context.context.account.id + let runningTasks: Signal = .single(nil) + |> then(watchManager.runningTasks) + return runningTasks + |> distinctUntilChanged + |> map { value -> AccountRecordId? in + if let value = value, value.running { + return accountId + } else { + return nil + } + } + |> distinctUntilChanged + } else { + return .single(nil) + } + } + let wakeupManager = SharedWakeupManager(beginBackgroundTask: { name, expiration in application.beginBackgroundTask(withName: name, expirationHandler: expiration) }, endBackgroundTask: { id in application.endBackgroundTask(id) }, backgroundTimeRemaining: { application.backgroundTimeRemaining }, activeAccounts: sharedContext.activeAccounts |> map { ($0.0, $0.1.map { ($0.0, $0.1) }) }, liveLocationPolling: liveLocationPolling, watchTasks: watchTasks, inForeground: applicationBindings.applicationInForeground, hasActiveAudioSession: self.hasActiveAudioSession.get(), notificationManager: notificationManager, mediaManager: sharedContext.mediaManager, callManager: sharedContext.callManager, accountUserInterfaceInUse: { id in + return sharedContext.accountUserInterfaceInUse(id) + }) + let sharedApplicationContext = SharedApplicationContext(sharedContext: sharedContext, notificationManager: notificationManager, wakeupManager: wakeupManager) + sharedApplicationContext.sharedContext.mediaManager.overlayMediaManager.attachOverlayMediaController(sharedApplicationContext.overlayMediaController) + + return accountManager.transaction { transaction -> (SharedApplicationContext, LoggingSettings) in + return (sharedApplicationContext, transaction.getSharedData(SharedDataKeys.loggingSettings) as? LoggingSettings ?? LoggingSettings.defaultSettings) } } - let watchTasks = self.context.get() - |> mapToSignal { context -> Signal in - if let context = context, let watchManager = context.context.watchManager { - let accountId = context.context.account.id - let runningTasks: Signal = .single(nil) - |> then(watchManager.runningTasks) - return runningTasks - |> distinctUntilChanged - |> map { value -> AccountRecordId? in - if let value = value, value.running { - return accountId - } else { - return nil - } - } - |> distinctUntilChanged - } else { - return .single(nil) - } - } - let wakeupManager = SharedWakeupManager(beginBackgroundTask: { name, expiration in application.beginBackgroundTask(withName: name, expirationHandler: expiration) }, endBackgroundTask: { id in application.endBackgroundTask(id) }, backgroundTimeRemaining: { application.backgroundTimeRemaining }, activeAccounts: sharedContext.activeAccounts |> map { ($0.0, $0.1.map { ($0.0, $0.1) }) }, liveLocationPolling: liveLocationPolling, watchTasks: watchTasks, inForeground: applicationBindings.applicationInForeground, hasActiveAudioSession: hasActiveAudioSession.get(), notificationManager: notificationManager, mediaManager: sharedContext.mediaManager, callManager: sharedContext.callManager, accountUserInterfaceInUse: { id in - return sharedContext.accountUserInterfaceInUse(id) - }) - let sharedApplicationContext = SharedApplicationContext(sharedContext: sharedContext, notificationManager: notificationManager, wakeupManager: wakeupManager) - sharedApplicationContext.sharedContext.mediaManager.overlayMediaManager.attachOverlayMediaController(sharedApplicationContext.overlayMediaController) - self.sharedContextPromise.set( - accountManager.transaction { transaction -> (SharedApplicationContext, LoggingSettings) in - return (sharedApplicationContext, transaction.getSharedData(SharedDataKeys.loggingSettings) as? LoggingSettings ?? LoggingSettings.defaultSettings) - } + self.sharedContextPromise.set(sharedContextSignal |> mapToSignal { sharedApplicationContext, loggingSettings -> Signal in Logger.shared.logToFile = loggingSettings.logToFile Logger.shared.logToConsole = loggingSettings.logToConsole @@ -793,7 +799,7 @@ private final class SharedApplicationContext { |> map { accountAndSettings -> AuthorizedApplicationContext? in return accountAndSettings.flatMap { account, limitsConfiguration, callListSettings in let context = AccountContext(sharedContext: sharedApplicationContext.sharedContext, account: account, limitsConfiguration: limitsConfiguration) - return AuthorizedApplicationContext(mainWindow: self.mainWindow, watchManagerArguments: watchManagerArgumentsPromise.get(), context: context, accountManager: sharedApplicationContext.sharedContext.accountManager, showCallsTab: callListSettings.showTab, reinitializedNotificationSettings: { + return AuthorizedApplicationContext(sharedApplicationContext: sharedApplicationContext, mainWindow: self.mainWindow, watchManagerArguments: watchManagerArgumentsPromise.get(), context: context, accountManager: sharedApplicationContext.sharedContext.accountManager, showCallsTab: callListSettings.showTab, reinitializedNotificationSettings: { let _ = (self.context.get() |> take(1) |> deliverOnMainQueue).start(next: { context in @@ -932,7 +938,7 @@ private final class SharedApplicationContext { } return true }) - self.mainWindow.topLevelOverlayControllers = [sharedApplicationContext.overlayMediaController, context.notificationController] + self.mainWindow.topLevelOverlayControllers = [context.sharedApplicationContext.overlayMediaController, context.notificationController] var authorizeNotifications = true if #available(iOS 10.0, *) { authorizeNotifications = false @@ -979,7 +985,10 @@ private final class SharedApplicationContext { })) self.watchCommunicationManagerPromise.set(watchCommunicationManager(context: self.context, allowBackgroundTimeExtension: { timeout in - wakeupManager.allowBackgroundTimeExtension(timeout: timeout) + let _ = (self.sharedContextPromise.get() + |> take(1)).start(next: { sharedContext in + sharedContext.wakeupManager.allowBackgroundTimeExtension(timeout: timeout) + }) })) let _ = self.watchCommunicationManagerPromise.get().start(next: { manager in if let manager = manager { @@ -1059,8 +1068,10 @@ private final class SharedApplicationContext { } })) } - let presentationData = sharedContext.currentPresentationData.with { $0 } - strongSelf.mainWindow.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: alert.title, text: alert.message ?? "", actions: actions), on: .root) + if let sharedContext = strongSelf.contextValue?.context.sharedContext { + let presentationData = sharedContext.currentPresentationData.with { $0 } + strongSelf.mainWindow.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: alert.title, text: alert.message ?? "", actions: actions), on: .root) + } } }) diff --git a/Telegram-iOS/ApplicationContext.swift b/Telegram-iOS/ApplicationContext.swift index 2edd30eac3..8c81c96174 100644 --- a/Telegram-iOS/ApplicationContext.swift +++ b/Telegram-iOS/ApplicationContext.swift @@ -46,6 +46,7 @@ private struct PasscodeState: Equatable { } final class AuthorizedApplicationContext { + let sharedApplicationContext: SharedApplicationContext let mainWindow: Window1 let lockedCoveringView: LockedWindowCoveringView @@ -99,7 +100,9 @@ final class AuthorizedApplicationContext { private var showCallsTabDisposable: Disposable? private var enablePostboxTransactionsDiposable: Disposable? - init(mainWindow: Window1, watchManagerArguments: Signal, context: AccountContext, accountManager: AccountManager, showCallsTab: Bool, reinitializedNotificationSettings: @escaping () -> Void) { + init(sharedApplicationContext: SharedApplicationContext, mainWindow: Window1, watchManagerArguments: Signal, context: AccountContext, accountManager: AccountManager, showCallsTab: Bool, reinitializedNotificationSettings: @escaping () -> Void) { + self.sharedApplicationContext = sharedApplicationContext + setupLegacyComponents(context: context) let presentationData = context.sharedContext.currentPresentationData.with { $0 } diff --git a/submodules/Postbox b/submodules/Postbox index 5debb55eb0..eca5668fc9 160000 --- a/submodules/Postbox +++ b/submodules/Postbox @@ -1 +1 @@ -Subproject commit 5debb55eb0cd0154b866857476bdfb8122308664 +Subproject commit eca5668fc9834be348e65edde3f4ec07eeffef0c diff --git a/submodules/TelegramCore b/submodules/TelegramCore index eb72b51295..fdcc098f80 160000 --- a/submodules/TelegramCore +++ b/submodules/TelegramCore @@ -1 +1 @@ -Subproject commit eb72b51295e0b0b937d4c0af59adb4fdce4d67a7 +Subproject commit fdcc098f8050834dd936f53a4476ac529abe6a58 diff --git a/submodules/TelegramUI b/submodules/TelegramUI index ae83518e5a..40ad8ff628 160000 --- a/submodules/TelegramUI +++ b/submodules/TelegramUI @@ -1 +1 @@ -Subproject commit ae83518e5a5fc2b79a9425891ad33962c3066ff9 +Subproject commit 40ad8ff62822372c08d7b4cb726316e5d0e5ac71