diff --git a/NotificationContent/NotificationViewController.swift b/NotificationContent/NotificationViewController.swift index 76abbbf2f0..c8c3bb0cf6 100644 --- a/NotificationContent/NotificationViewController.swift +++ b/NotificationContent/NotificationViewController.swift @@ -117,7 +117,7 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown" - sharedAccountContext = SharedAccountContext(mainWindow: nil, accountManager: accountManager, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0), rootPath: rootPath, apsNotificationToken: .never(), voipNotificationToken: .never(), setNotificationCall: { _ in }) + sharedAccountContext = SharedAccountContext(mainWindow: nil, accountManager: accountManager, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0), rootPath: rootPath, apsNotificationToken: .never(), voipNotificationToken: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _ in }) } } diff --git a/Share/ShareRootController.swift b/Share/ShareRootController.swift index 74ff67f1a2..3a4428b534 100644 --- a/Share/ShareRootController.swift +++ b/Share/ShareRootController.swift @@ -5,7 +5,7 @@ import TelegramUI import SwiftSignalKit import Postbox -private var accountCache: (SharedAccountContext, Account)? +private var sharedContextCache: SharedAccountContext? private var installedSharedLogger = false @@ -136,9 +136,10 @@ class ShareRootController: UIViewController { }, dismissNativeController: { }) - let account: Signal<(SharedAccountContext, Account), ShareAuthorizationError> - if let accountCache = accountCache { - account = .single(accountCache) + let sharedContext: SharedAccountContext + + if let sharedContextCache = sharedContextCache { + sharedContext = sharedContextCache } else { let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown" @@ -152,43 +153,38 @@ class ShareRootController: UIViewController { }) semaphore.wait() - let sharedContext = SharedAccountContext(mainWindow: nil, accountManager: accountManager, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0), rootPath: rootPath, apsNotificationToken: .never(), voipNotificationToken: .never(), setNotificationCall: { _ in }) - - account = accountManager.transaction { transaction -> (SharedAccountContext, LoggingSettings) in - return (sharedContext, transaction.getSharedData(SharedDataKeys.loggingSettings) as? LoggingSettings ?? LoggingSettings.defaultSettings) - } - |> introduceError(ShareAuthorizationError.self) - |> mapToSignal { sharedContext, loggingSettings -> Signal<(SharedAccountContext, Account), ShareAuthorizationError> in - Logger.shared.logToFile = loggingSettings.logToFile - Logger.shared.logToConsole = loggingSettings.logToConsole - - Logger.shared.redactSensitiveData = loggingSettings.redactSensitiveData - - preconditionFailure() - - /*return currentAccount(allocateIfNotExists: false, networkArguments: , supplementary: true, manager: sharedContext.accountManager, rootPath: rootPath, auxiliaryMethods: telegramAccountAuxiliaryMethods) - |> introduceError(ShareAuthorizationError.self) - |> mapToSignal { account -> Signal<(SharedAccountContext, Account), ShareAuthorizationError> in - if let account = account { - switch account { - case .upgrading: - return .complete() - case let .authorized(account): - return .single((sharedContext, account)) - case .unauthorized: - return .fail(.unauthorized) - } - } else { - return .complete() - } - }*/ - } - |> take(1) + sharedContext = SharedAccountContext(mainWindow: nil, accountManager: accountManager, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0), rootPath: rootPath, apsNotificationToken: .never(), voipNotificationToken: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _ in }) + sharedContextCache = sharedContext } + let account: Signal<(SharedAccountContext, Account, [AccountWithInfo]), ShareAuthorizationError> = sharedContext.accountManager.transaction { transaction -> (SharedAccountContext, LoggingSettings) in + return (sharedContext, transaction.getSharedData(SharedDataKeys.loggingSettings) as? LoggingSettings ?? LoggingSettings.defaultSettings) + } + |> introduceError(ShareAuthorizationError.self) + |> mapToSignal { sharedContext, loggingSettings -> Signal<(SharedAccountContext, Account, [AccountWithInfo]), ShareAuthorizationError> in + Logger.shared.logToFile = loggingSettings.logToFile + Logger.shared.logToConsole = loggingSettings.logToConsole + + Logger.shared.redactSensitiveData = loggingSettings.redactSensitiveData + + return sharedContext.activeAccountsWithInfo + |> introduceError(ShareAuthorizationError.self) + |> take(1) + |> mapToSignal { primary, accounts -> Signal<(SharedAccountContext, Account, [AccountWithInfo]), ShareAuthorizationError> in + guard let primary = primary else { + return .fail(.unauthorized) + } + guard let info = accounts[primary] else { + return .fail(.unauthorized) + } + return .single((sharedContext, info.account, Array(accounts.values))) + } + } + |> take(1) + let shouldBeMaster = self.shouldBeMaster let applicationInterface = account - |> mapToSignal { sharedContext, account -> Signal<(AccountContext, PostboxAccessChallengeData), ShareAuthorizationError> in + |> mapToSignal { sharedContext, account, otherAccounts -> Signal<(AccountContext, PostboxAccessChallengeData, [AccountWithInfo]), ShareAuthorizationError> in let limitsConfiguration = account.postbox.transaction { transaction -> LimitsConfiguration in return transaction.getPreferencesEntry(key: PreferencesKeys.limitsConfiguration) as? LimitsConfiguration ?? LimitsConfiguration.defaultValue } @@ -196,15 +192,14 @@ class ShareRootController: UIViewController { |> take(1) |> deliverOnMainQueue |> introduceError(ShareAuthorizationError.self) - |> map { sharedData, limitsConfiguration, data -> (AccountContext, PostboxAccessChallengeData) in - accountCache = (sharedContext, account) + |> map { sharedData, limitsConfiguration, data -> (AccountContext, PostboxAccessChallengeData, [AccountWithInfo]) in updateLegacyLocalization(strings: sharedContext.currentPresentationData.with({ $0 }).strings) let context = AccountContext(sharedContext: sharedContext, account: account, limitsConfiguration: limitsConfiguration) - return (context, data.data) + return (context, data.data, otherAccounts) } } |> deliverOnMainQueue - |> afterNext { [weak self] context, accessChallengeData in + |> afterNext { [weak self] context, accessChallengeData, otherAccounts in setupAccount(context.account) setupLegacyComponents(context: context) initializeLegacyComponents(application: nil, currentSizeClassGetter: { return .compact }, currentHorizontalClassGetter: { return .compact }, documentsPath: "", currentApplicationBounds: { return CGRect() }, canOpenUrl: { _ in return false}, openUrl: { _ in }) @@ -280,7 +275,7 @@ class ShareRootController: UIViewController { } else { return .single(.done) } - }), externalShare: false) + }), externalShare: false, switchableAccounts: otherAccounts) shareController.presentationArguments = ViewControllerPresentationArguments(presentationAnimation: .modalSheet) shareController.dismissed = { _ in self?.extensionContext?.completeRequest(returningItems: nil, completionHandler: nil) @@ -390,14 +385,13 @@ class ShareRootController: UIViewController { legacyController.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .portrait, compactSize: .portrait) legacyController.statusBar.statusBarStyle = .White */ - } - self.disposable.set(applicationInterface.start(next: { _, _ in }, error: { [weak self] error in + self.disposable.set(applicationInterface.start(next: { _, _, _ in }, error: { [weak self] error in guard let strongSelf = self else { return } - let presentationData = defaultPresentationData() + let presentationData = sharedContext.currentPresentationData.with { $0 } let controller = standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: presentationData.strings.Share_AuthTitle, text: presentationData.strings.Share_AuthDescription, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: { self?.extensionContext?.completeRequest(returningItems: nil, completionHandler: nil) })]) diff --git a/Telegram-iOS/AppDelegate.swift b/Telegram-iOS/AppDelegate.swift index 61e68cdbbb..abd33812fd 100644 --- a/Telegram-iOS/AppDelegate.swift +++ b/Telegram-iOS/AppDelegate.swift @@ -619,6 +619,8 @@ private final class SharedApplicationContext { var setPresentationCall: ((PresentationCall?) -> Void)? let sharedContext = SharedAccountContext(mainWindow: self.mainWindow, accountManager: accountManager, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: networkArguments, rootPath: rootPath, 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) }) sharedContext.presentGlobalController = { [weak self] c, a in guard let strongSelf = self else { @@ -675,7 +677,9 @@ private final class SharedApplicationContext { return .single(nil) } } - let wakeupManager = SharedWakeupManager(activeAccounts: sharedContext.activeAccounts |> map { ($0.0, $0.1) }, liveLocationPolling: liveLocationPolling, inForeground: applicationBindings.applicationInForeground, hasActiveAudioSession: hasActiveAudioSession.get(), notificationManager: notificationManager, mediaManager: sharedContext.mediaManager, callManager: sharedContext.callManager) + let wakeupManager = SharedWakeupManager(activeAccounts: sharedContext.activeAccounts |> map { ($0.0, $0.1) }, liveLocationPolling: liveLocationPolling, 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) self.sharedContextPromise.set( accountManager.transaction { transaction -> (SharedApplicationContext, LoggingSettings) in @@ -810,41 +814,54 @@ private final class SharedApplicationContext { |> deliverOnMainQueue |> mapToSignal { sharedApplicationContext -> Signal in return sharedApplicationContext.sharedContext.activeAccounts - |> map { _, accounts, auth -> (UnauthorizedAccount, [Account])? in + |> map { primary, accounts, auth -> (Account?, UnauthorizedAccount, [Account])? in if let auth = auth { - return (auth, Array(accounts.values)) + return (primary, auth, Array(accounts.values)) } else { return nil } } |> distinctUntilChanged(isEqual: { lhs, rhs in - if lhs?.0 !== rhs?.0 { + if lhs?.1 !== rhs?.1 { return false } return true }) - |> mapToSignal { authAndAccounts -> Signal<(UnauthorizedAccount, [String])?, NoError> in - if let (auth, accounts) = authAndAccounts { - let phoneNumbers = combineLatest(accounts.map { account -> Signal in - return account.postbox.transaction { transaction -> String? in - return (transaction.getPeer(account.peerId) as? TelegramUser)?.phone + |> mapToSignal { authAndAccounts -> Signal<(UnauthorizedAccount, ((String, AccountRecordId)?, [(String, AccountRecordId)]))?, NoError> in + if let (primary, auth, accounts) = authAndAccounts { + let phoneNumbers = combineLatest(accounts.map { account -> Signal<(AccountRecordId, String)?, NoError> in + return account.postbox.transaction { transaction -> (AccountRecordId, String)? in + if let phone = (transaction.getPeer(account.peerId) as? TelegramUser)?.phone { + return (account.id, phone) + } else { + return nil + } } }) return phoneNumbers - |> map { phoneNumbers -> (UnauthorizedAccount, [String])? in - return (auth, phoneNumbers.compactMap({ $0 })) + |> map { phoneNumbers -> (UnauthorizedAccount, ((String, AccountRecordId)?, [(String, AccountRecordId)]))? in + var primaryNumber: (String, AccountRecordId)? + if let primary = primary { + for idAndNumber in phoneNumbers { + if let (id, number) = idAndNumber, id == primary.id { + primaryNumber = (number, id) + break + } + } + } + return (auth, (primaryNumber, phoneNumbers.compactMap({ $0.flatMap({ ($0.1, $0.0) }) }))) } } else { return .single(nil) } } - |> mapToSignal { accountAndOtherAccountPhoneNumbers -> Signal<(UnauthorizedAccount, LimitsConfiguration, CallListSettings, [String])?, NoError> in + |> mapToSignal { accountAndOtherAccountPhoneNumbers -> Signal<(UnauthorizedAccount, LimitsConfiguration, CallListSettings, ((String, AccountRecordId)?, [(String, AccountRecordId)]))?, NoError> in return sharedApplicationContext.sharedContext.accountManager.transaction { transaction -> CallListSettings in return transaction.getSharedData(ApplicationSpecificSharedDataKeys.callListSettings) as? CallListSettings ?? CallListSettings.defaultSettings } - |> mapToSignal { callListSettings -> Signal<(UnauthorizedAccount, LimitsConfiguration, CallListSettings, [String])?, NoError> in + |> mapToSignal { callListSettings -> Signal<(UnauthorizedAccount, LimitsConfiguration, CallListSettings, ((String, AccountRecordId)?, [(String, AccountRecordId)]))?, NoError> in if let (account, otherAccountPhoneNumbers) = accountAndOtherAccountPhoneNumbers { - return account.postbox.transaction { transaction -> (UnauthorizedAccount, LimitsConfiguration, CallListSettings, [String])? in + return account.postbox.transaction { transaction -> (UnauthorizedAccount, LimitsConfiguration, CallListSettings, ((String, AccountRecordId)?, [(String, AccountRecordId)]))? in let limitsConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.limitsConfiguration) as? LimitsConfiguration ?? LimitsConfiguration.defaultValue return (account, limitsConfiguration, callListSettings, otherAccountPhoneNumbers) } diff --git a/Telegram-iOS/ApplicationContext.swift b/Telegram-iOS/ApplicationContext.swift index 63da894a82..eebc1866d0 100644 --- a/Telegram-iOS/ApplicationContext.swift +++ b/Telegram-iOS/ApplicationContext.swift @@ -63,7 +63,7 @@ final class UnauthorizedApplicationContext { let rootController: AuthorizationSequenceController - init(sharedContext: SharedAccountContext, account: UnauthorizedAccount, otherAccountPhoneNumbers: [String]) { + init(sharedContext: SharedAccountContext, account: UnauthorizedAccount, otherAccountPhoneNumbers: ((String, AccountRecordId)?, [(String, AccountRecordId)])) { self.sharedContext = sharedContext self.account = account self.strings = defaultPresentationStrings @@ -134,7 +134,7 @@ final class AuthorizedApplicationContext { } } - let isReady = ValuePromise(false, ignoreRepeated: true) + let isReady = Promise() private var presentationDataDisposable: Disposable? private var displayAlertsDisposable: Disposable? @@ -157,13 +157,6 @@ final class AuthorizedApplicationContext { self.replyFromNotificationsActive = replyFromNotificationsActive self.backgroundAudioActive = backgroundAudioActive - let runningBackgroundLocationTasks: Signal - if let liveLocationManager = context.liveLocationManager { - runningBackgroundLocationTasks = liveLocationManager.isPolling - } else { - runningBackgroundLocationTasks = .single(false) - } - let runningWatchTasksPromise = Promise(nil) let runningDownloadTasks = combineLatest(context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.automaticMediaDownloadSettings]), context.account.shouldKeepBackgroundDownloadConnections.get()) @@ -488,7 +481,12 @@ final class AuthorizedApplicationContext { transaction.setAccessChallengeData(data) }).start() }*/ - strongSelf.isReady.set(true) + if let tabsController = strongSelf.rootController.viewControllers.first as? TabBarController, !tabsController.controllers.isEmpty, tabsController.selectedIndex >= 0 { + let controller = tabsController.controllers[tabsController.selectedIndex] + strongSelf.isReady.set(controller.ready.get()) + } else { + strongSelf.isReady.set(.single(true)) + } })) let accountId = context.account.id diff --git a/Telegram-iOS/SharedWakeupManager.swift b/Telegram-iOS/SharedWakeupManager.swift index 1f2c0a2014..bc14016fd8 100644 --- a/Telegram-iOS/SharedWakeupManager.swift +++ b/Telegram-iOS/SharedWakeupManager.swift @@ -12,6 +12,7 @@ private struct AccountTasks { let backgroundDownloads: Bool let backgroundAudio: Bool let activeCalls: Bool + let userInterfaceInUse: Bool var isEmpty: Bool { if self.stateSynchronization { @@ -32,6 +33,9 @@ private struct AccountTasks { if self.activeCalls { return false } + if self.userInterfaceInUse { + return false + } return true } } @@ -49,7 +53,7 @@ final class SharedWakeupManager { private var accountsAndTasks: [(Account, Bool, AccountTasks)] = [] - init(activeAccounts: Signal<(primary: Account?, accounts: [AccountRecordId: Account]), NoError>, liveLocationPolling: Signal, inForeground: Signal, hasActiveAudioSession: Signal, notificationManager: SharedNotificationManager, mediaManager: MediaManager, callManager: PresentationCallManager?) { + init(activeAccounts: Signal<(primary: Account?, accounts: [AccountRecordId: Account]), NoError>, liveLocationPolling: Signal, inForeground: Signal, hasActiveAudioSession: Signal, notificationManager: SharedNotificationManager, mediaManager: MediaManager, callManager: PresentationCallManager?, accountUserInterfaceInUse: @escaping (AccountRecordId) -> Signal) { assert(Queue.mainQueue().isCurrent()) self.inForegroundDisposable = (inForeground @@ -108,9 +112,11 @@ final class SharedWakeupManager { } |> distinctUntilChanged - return combineLatest(queue: .mainQueue(), account.importantTasksRunning, notificationManager.isPollingState(accountId: account.id), hasActiveAudio, hasActiveCalls, hasActiveLiveLocationPolling) - |> map { importantTasksRunning, isPollingState, hasActiveAudio, hasActiveCalls, hasActiveLiveLocationPolling -> (Account, Bool, AccountTasks) in - return (account, primary?.id == account.id, AccountTasks(stateSynchronization: isPollingState, importantTasks: importantTasksRunning, backgroundLocation: hasActiveLiveLocationPolling, backgroundDownloads: false, backgroundAudio: hasActiveAudio, activeCalls: hasActiveCalls)) + let userInterfaceInUse = accountUserInterfaceInUse(account.id) + + return combineLatest(queue: .mainQueue(), account.importantTasksRunning, notificationManager.isPollingState(accountId: account.id), hasActiveAudio, hasActiveCalls, hasActiveLiveLocationPolling, userInterfaceInUse) + |> map { importantTasksRunning, isPollingState, hasActiveAudio, hasActiveCalls, hasActiveLiveLocationPolling, userInterfaceInUse -> (Account, Bool, AccountTasks) in + return (account, primary?.id == account.id, AccountTasks(stateSynchronization: isPollingState, importantTasks: importantTasksRunning, backgroundLocation: hasActiveLiveLocationPolling, backgroundDownloads: false, backgroundAudio: hasActiveAudio, activeCalls: hasActiveCalls, userInterfaceInUse: userInterfaceInUse)) } } return combineLatest(signals) diff --git a/Telegram-iOS/en.lproj/Localizable.strings b/Telegram-iOS/en.lproj/Localizable.strings index 12b03dafe1..c29f64ca40 100644 --- a/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram-iOS/en.lproj/Localizable.strings @@ -3921,6 +3921,7 @@ Unused sets are archived when you add more."; "ChatList.DeleteChatConfirmation" = "Are you sure you want to delete chat\nwith %@?"; "ChatList.DeleteSecretChatConfirmation" = "Are you sure you want to delete secret chat\nwith %@?"; "ChatList.LeaveGroupConfirmation" = "Are you sure you want to leave %@?"; +"ChatList.DeleteSavedMessagesConfirmation" = "Are you sure you want to delete\nSaved Messages?"; "Undo.Undo" = "Undo"; "Undo.MessagesDeleted" = "Messages deleted"; @@ -3971,3 +3972,6 @@ Unused sets are archived when you add more."; "SocksProxySetup.Status" = "Status"; "Login.PhoneNumberAlreadyAuthorized" = "This account is already logged in from this app."; +"Login.PhoneNumberAlreadyAuthorizedSwitch" = "Switch"; + +"Call.AnsweringWithAccount" = "Answering as %@"; diff --git a/submodules/AsyncDisplayKit b/submodules/AsyncDisplayKit index 711f2e46be..e4068e7da4 160000 --- a/submodules/AsyncDisplayKit +++ b/submodules/AsyncDisplayKit @@ -1 +1 @@ -Subproject commit 711f2e46be8d366805e65166ecade31f8b342eb4 +Subproject commit e4068e7da4b7c484f82e68108744c2d048d5859a diff --git a/submodules/Display b/submodules/Display index 947810ca9c..275fd01964 160000 --- a/submodules/Display +++ b/submodules/Display @@ -1 +1 @@ -Subproject commit 947810ca9cef45f04497d064ea6be876cfb524f5 +Subproject commit 275fd019647a2c1e7940d97458bde38a82f34137 diff --git a/submodules/TelegramCore b/submodules/TelegramCore index 728a062ab8..03563113d1 160000 --- a/submodules/TelegramCore +++ b/submodules/TelegramCore @@ -1 +1 @@ -Subproject commit 728a062ab88b3d607bfb61f6fb5dccd6bce7e1ec +Subproject commit 03563113d1b2816dbae820bfc358c50169110156 diff --git a/submodules/TelegramUI b/submodules/TelegramUI index 31106626c2..94b5a8fa56 160000 --- a/submodules/TelegramUI +++ b/submodules/TelegramUI @@ -1 +1 @@ -Subproject commit 31106626c209d018ad93c447e373b8ec99508531 +Subproject commit 94b5a8fa56f7793c3ca32043db2272ea34a8e3fd