Multiaccount api updates

This commit is contained in:
Peter Iakovlev 2019-02-08 17:57:04 +04:00
parent 878c6044e7
commit 3c6f3d9235
10 changed files with 97 additions and 78 deletions

View File

@ -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 })
}
}

View File

@ -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)
})])

View File

@ -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<UnauthorizedApplicationContext?, NoError> 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<String?, NoError> 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)
}

View File

@ -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<Bool>(false, ignoreRepeated: true)
let isReady = Promise<Bool>()
private var presentationDataDisposable: Disposable?
private var displayAlertsDisposable: Disposable?
@ -157,13 +157,6 @@ final class AuthorizedApplicationContext {
self.replyFromNotificationsActive = replyFromNotificationsActive
self.backgroundAudioActive = backgroundAudioActive
let runningBackgroundLocationTasks: Signal<Bool, NoError>
if let liveLocationManager = context.liveLocationManager {
runningBackgroundLocationTasks = liveLocationManager.isPolling
} else {
runningBackgroundLocationTasks = .single(false)
}
let runningWatchTasksPromise = Promise<WatchRunningTasks?>(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

View File

@ -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<AccountRecordId?, NoError>, inForeground: Signal<Bool, NoError>, hasActiveAudioSession: Signal<Bool, NoError>, notificationManager: SharedNotificationManager, mediaManager: MediaManager, callManager: PresentationCallManager?) {
init(activeAccounts: Signal<(primary: Account?, accounts: [AccountRecordId: Account]), NoError>, liveLocationPolling: Signal<AccountRecordId?, NoError>, inForeground: Signal<Bool, NoError>, hasActiveAudioSession: Signal<Bool, NoError>, notificationManager: SharedNotificationManager, mediaManager: MediaManager, callManager: PresentationCallManager?, accountUserInterfaceInUse: @escaping (AccountRecordId) -> Signal<Bool, NoError>) {
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)

View File

@ -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 %@";

@ -1 +1 @@
Subproject commit 711f2e46be8d366805e65166ecade31f8b342eb4
Subproject commit e4068e7da4b7c484f82e68108744c2d048d5859a

@ -1 +1 @@
Subproject commit 947810ca9cef45f04497d064ea6be876cfb524f5
Subproject commit 275fd019647a2c1e7940d97458bde38a82f34137

@ -1 +1 @@
Subproject commit 728a062ab88b3d607bfb61f6fb5dccd6bce7e1ec
Subproject commit 03563113d1b2816dbae820bfc358c50169110156

@ -1 +1 @@
Subproject commit 31106626c209d018ad93c447e373b8ec99508531
Subproject commit 94b5a8fa56f7793c3ca32043db2272ea34a8e3fd