mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-04 21:41:45 +00:00
Improved account switching
This commit is contained in:
parent
4a6a24226e
commit
3e851a0fe8
@ -5,7 +5,7 @@ import TelegramUI
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
|
||||
private var accountCache: (Account, AccountManager)?
|
||||
private var accountCache: (SharedAccountContext, Account)?
|
||||
|
||||
private var installedSharedLogger = false
|
||||
|
||||
@ -136,7 +136,7 @@ class ShareRootController: UIViewController {
|
||||
}, dismissNativeController: {
|
||||
})
|
||||
|
||||
let account: Signal<(Account, AccountManager), ShareAuthorizationError>
|
||||
let account: Signal<(SharedAccountContext, Account), ShareAuthorizationError>
|
||||
if let accountCache = accountCache {
|
||||
account = .single(accountCache)
|
||||
} else {
|
||||
@ -145,33 +145,38 @@ class ShareRootController: UIViewController {
|
||||
initializeAccountManagement()
|
||||
account = accountManager(basePath: rootPath + "/accounts-metadata")
|
||||
|> take(1)
|
||||
|> mapToSignal { accountManager -> Signal<(AccountManager, LoggingSettings), NoError> in
|
||||
return accountManager.transaction { transaction -> (AccountManager, LoggingSettings) in
|
||||
return (accountManager, transaction.getSharedData(SharedDataKeys.loggingSettings) as? LoggingSettings ?? LoggingSettings.defaultSettings)
|
||||
|> mapToSignal { accountManager -> Signal<(SharedAccountContext, LoggingSettings), NoError> in
|
||||
let sharedContext = SharedAccountContext(accountManager: accountManager, applicationBindings: applicationBindings, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0), rootPath: rootPath, apsNotificationToken: .never(), voipNotificationToken: .never())
|
||||
|
||||
return accountManager.transaction { transaction -> (SharedAccountContext, LoggingSettings) in
|
||||
return (sharedContext, transaction.getSharedData(SharedDataKeys.loggingSettings) as? LoggingSettings ?? LoggingSettings.defaultSettings)
|
||||
}
|
||||
}
|
||||
|> introduceError(ShareAuthorizationError.self)
|
||||
|> mapToSignal { accountManager, loggingSettings -> Signal<(Account, AccountManager), ShareAuthorizationError> in
|
||||
|> mapToSignal { sharedContext, loggingSettings -> Signal<(SharedAccountContext, Account), ShareAuthorizationError> in
|
||||
Logger.shared.logToFile = loggingSettings.logToFile
|
||||
Logger.shared.logToConsole = loggingSettings.logToConsole
|
||||
|
||||
Logger.shared.redactSensitiveData = loggingSettings.redactSensitiveData
|
||||
|
||||
return currentAccount(allocateIfNotExists: false, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0), supplementary: true, manager: accountManager, rootPath: rootPath, auxiliaryMethods: telegramAccountAuxiliaryMethods)
|
||||
|> introduceError(ShareAuthorizationError.self) |> mapToSignal { account -> Signal<(Account, AccountManager), ShareAuthorizationError> in
|
||||
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((account, accountManager))
|
||||
return .single((sharedContext, account))
|
||||
case .unauthorized:
|
||||
return .fail(.unauthorized)
|
||||
}
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|> take(1)
|
||||
}
|
||||
@ -180,14 +185,14 @@ class ShareRootController: UIViewController {
|
||||
|
||||
let shouldBeMaster = self.shouldBeMaster
|
||||
let applicationInterface = account
|
||||
|> mapToSignal { account, accountManager -> Signal<(AccountContext, PostboxAccessChallengeData), ShareAuthorizationError> in
|
||||
|> mapToSignal { sharedContext, account -> Signal<(AccountContext, PostboxAccessChallengeData), ShareAuthorizationError> in
|
||||
return combineLatest(currentPresentationDataAndSettings(postbox: account.postbox), account.postbox.combinedView(keys: [.accessChallengeData, preferencesKey]) |> take(1))
|
||||
|> deliverOnMainQueue
|
||||
|> introduceError(ShareAuthorizationError.self)
|
||||
|> map { dataAndSettings, data -> (AccountContext, PostboxAccessChallengeData) in
|
||||
accountCache = (account, accountManager)
|
||||
accountCache = (sharedContext, account)
|
||||
updateLegacyLocalization(strings: dataAndSettings.presentationData.strings)
|
||||
let context = AccountContext(account: account, applicationBindings: applicationBindings, accountManager: accountManager, initialPresentationDataAndSettings: dataAndSettings, postbox: account.postbox)
|
||||
let context = AccountContext(sharedContext: sharedContext, account: account, initialPresentationDataAndSettings: dataAndSettings)
|
||||
return (context, (data.views[.accessChallengeData] as! AccessChallengeDataView).data)
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,7 +134,7 @@ private enum QueuedWakeup: Int32 {
|
||||
private var isActiveValue = false
|
||||
let hasActiveAudioSession = Promise<Bool>(false)
|
||||
|
||||
private let accountManagerPromise = Promise<AccountManager>()
|
||||
private let sharedContextPromise = Promise<SharedAccountContext>()
|
||||
private let watchCommunicationManagerPromise = Promise<WatchCommunicationManager?>()
|
||||
|
||||
private var contextValue: ApplicationContext?
|
||||
@ -444,86 +444,6 @@ private enum QueuedWakeup: Int32 {
|
||||
self.hasActiveAudioSession.set(MediaManager.globalAudioSession.isActive())
|
||||
|
||||
initializeAccountManagement()
|
||||
self.accountManagerPromise.set(accountManager(basePath: rootPath + "/accounts-metadata")
|
||||
|> mapToSignal { accountManager -> Signal<(AccountManager, LoggingSettings), NoError> in
|
||||
return accountManager.transaction { transaction -> (AccountManager, LoggingSettings) in
|
||||
return (accountManager, transaction.getSharedData(SharedDataKeys.loggingSettings) as? LoggingSettings ?? LoggingSettings.defaultSettings)
|
||||
}
|
||||
}
|
||||
|> mapToSignal { accountManager, loggingSettings -> Signal<AccountManager, NoError> in
|
||||
AccountStore.initialize(accountManager: accountManager)
|
||||
|
||||
Logger.shared.logToFile = loggingSettings.logToFile
|
||||
Logger.shared.logToConsole = loggingSettings.logToConsole
|
||||
Logger.shared.redactSensitiveData = loggingSettings.redactSensitiveData
|
||||
|
||||
return importedLegacyAccount(basePath: appGroupUrl.path, accountManager: accountManager, present: { controller in
|
||||
self.window?.rootViewController?.present(controller, animated: true, completion: nil)
|
||||
})
|
||||
|> `catch` { _ -> Signal<ImportedLegacyAccountEvent, NoError> in
|
||||
return Signal { subscriber in
|
||||
let alertView = UIAlertView(title: "", message: "An error occured while trying to upgrade application data. Would you like to logout?", delegate: self, cancelButtonTitle: "No", otherButtonTitles: "Yes")
|
||||
self.alertActions = (primary: {
|
||||
let statusPath = appGroupUrl.path + "/Documents/importcompleted"
|
||||
let _ = try? FileManager.default.createDirectory(atPath: appGroupUrl.path + "/Documents", withIntermediateDirectories: true, attributes: nil)
|
||||
let _ = try? Data().write(to: URL(fileURLWithPath: statusPath))
|
||||
subscriber.putNext(.result(nil))
|
||||
subscriber.putCompletion()
|
||||
}, other: {
|
||||
exit(0)
|
||||
})
|
||||
alertView.show()
|
||||
|
||||
return EmptyDisposable
|
||||
} |> runOn(Queue.mainQueue())
|
||||
}
|
||||
|> mapToSignal { event -> Signal<AccountManager, NoError> in
|
||||
switch event {
|
||||
case let .progress(type, value):
|
||||
Queue.mainQueue().async {
|
||||
if self.dataImportSplash == nil {
|
||||
self.dataImportSplash = LegacyDataImportSplash()
|
||||
self.dataImportSplash?.serviceAction = {
|
||||
self.debugPressed()
|
||||
}
|
||||
self.mainWindow.coveringView = self.dataImportSplash
|
||||
}
|
||||
self.dataImportSplash?.progress = (type, value)
|
||||
}
|
||||
return .complete()
|
||||
case let .result(temporaryId):
|
||||
Queue.mainQueue().async {
|
||||
if let _ = self.dataImportSplash {
|
||||
self.dataImportSplash = nil
|
||||
self.mainWindow.coveringView = nil
|
||||
}
|
||||
}
|
||||
if let temporaryId = temporaryId {
|
||||
Queue.mainQueue().after(1.0, {
|
||||
let statusPath = appGroupUrl.path + "/Documents/importcompleted"
|
||||
let _ = try? FileManager.default.createDirectory(atPath: appGroupUrl.path + "/Documents", withIntermediateDirectories: true, attributes: nil)
|
||||
let _ = try? Data().write(to: URL(fileURLWithPath: statusPath))
|
||||
})
|
||||
return accountManager.transaction { transaction -> AccountManager in
|
||||
transaction.setCurrentId(temporaryId)
|
||||
transaction.updateRecord(temporaryId, { record in
|
||||
if let record = record {
|
||||
return AccountRecord(id: record.id, attributes: record.attributes, temporarySessionId: nil)
|
||||
}
|
||||
return record
|
||||
})
|
||||
return accountManager
|
||||
}
|
||||
}
|
||||
return .single(accountManager)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let _ = (self.accountManagerPromise.get()
|
||||
|> mapToSignal { manager in
|
||||
return managedCleanupAccounts(networkArguments: networkArguments, accountManager: manager, rootPath: rootPath, auxiliaryMethods: telegramAccountAuxiliaryMethods)
|
||||
}).start()
|
||||
|
||||
let applicationBindings = TelegramApplicationBindings(isMainApp: true, containerPath: appGroupUrl.path, appSpecificScheme: BuildConfig.shared().appSpecificUrlScheme, openUrl: { url in
|
||||
var parsedUrl = URL(string: url)
|
||||
@ -663,25 +583,143 @@ private enum QueuedWakeup: Int32 {
|
||||
self.window?.rootViewController?.dismiss(animated: true, completion: nil)
|
||||
})
|
||||
|
||||
let watchManagerArgumentsPromise = Promise<WatchManagerArguments?>()
|
||||
|
||||
self.context.set(self.accountManagerPromise.get()
|
||||
self.sharedContextPromise.set(accountManager(basePath: rootPath + "/accounts-metadata")
|
||||
|> deliverOnMainQueue
|
||||
|> mapToSignal { accountManager -> Signal<ApplicationContext?, NoError> in
|
||||
let replyFromNotificationsActive = self.replyFromNotificationsTokensPromise.get()
|
||||
|> map {
|
||||
!$0.isEmpty
|
||||
|> mapToSignal { accountManager -> Signal<(SharedAccountContext, LoggingSettings), NoError> in
|
||||
let sharedContext = SharedAccountContext(accountManager: accountManager, applicationBindings: applicationBindings, networkArguments: networkArguments, rootPath: rootPath, apsNotificationToken: self.notificationTokenPromise.get() |> map(Optional.init), voipNotificationToken: self.voipTokenPromise.get() |> map(Optional.init))
|
||||
return accountManager.transaction { transaction -> (SharedAccountContext, LoggingSettings) in
|
||||
return (sharedContext, transaction.getSharedData(SharedDataKeys.loggingSettings) as? LoggingSettings ?? LoggingSettings.defaultSettings)
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
return applicationContext(networkArguments: networkArguments, applicationBindings: applicationBindings, replyFromNotificationsActive: replyFromNotificationsActive, backgroundAudioActive: self.hasActiveAudioSession.get() |> distinctUntilChanged, watchManagerArguments: watchManagerArgumentsPromise.get(), accountManager: accountManager, rootPath: rootPath, legacyBasePath: appGroupUrl.path, mainWindow: self.mainWindow, reinitializedNotificationSettings: {
|
||||
let _ = (self.context.get()
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { value in
|
||||
if let value = value, case let .authorized(context) = value {
|
||||
self.registerForNotifications(context: context.context, authorize: false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|> mapToSignal { sharedContext, loggingSettings -> Signal<SharedAccountContext, NoError> in
|
||||
Logger.shared.logToFile = loggingSettings.logToFile
|
||||
Logger.shared.logToConsole = loggingSettings.logToConsole
|
||||
Logger.shared.redactSensitiveData = loggingSettings.redactSensitiveData
|
||||
|
||||
return importedLegacyAccount(basePath: appGroupUrl.path, accountManager: sharedContext.accountManager, present: { controller in
|
||||
self.window?.rootViewController?.present(controller, animated: true, completion: nil)
|
||||
})
|
||||
|> `catch` { _ -> Signal<ImportedLegacyAccountEvent, NoError> in
|
||||
return Signal { subscriber in
|
||||
let alertView = UIAlertView(title: "", message: "An error occured while trying to upgrade application data. Would you like to logout?", delegate: self, cancelButtonTitle: "No", otherButtonTitles: "Yes")
|
||||
self.alertActions = (primary: {
|
||||
let statusPath = appGroupUrl.path + "/Documents/importcompleted"
|
||||
let _ = try? FileManager.default.createDirectory(atPath: appGroupUrl.path + "/Documents", withIntermediateDirectories: true, attributes: nil)
|
||||
let _ = try? Data().write(to: URL(fileURLWithPath: statusPath))
|
||||
subscriber.putNext(.result(nil))
|
||||
subscriber.putCompletion()
|
||||
}, other: {
|
||||
exit(0)
|
||||
})
|
||||
alertView.show()
|
||||
|
||||
return EmptyDisposable
|
||||
} |> runOn(Queue.mainQueue())
|
||||
}
|
||||
|> mapToSignal { event -> Signal<SharedAccountContext, NoError> in
|
||||
switch event {
|
||||
case let .progress(type, value):
|
||||
Queue.mainQueue().async {
|
||||
if self.dataImportSplash == nil {
|
||||
self.dataImportSplash = LegacyDataImportSplash()
|
||||
self.dataImportSplash?.serviceAction = {
|
||||
self.debugPressed()
|
||||
}
|
||||
self.mainWindow.coveringView = self.dataImportSplash
|
||||
}
|
||||
self.dataImportSplash?.progress = (type, value)
|
||||
}
|
||||
return .complete()
|
||||
case let .result(temporaryId):
|
||||
Queue.mainQueue().async {
|
||||
if let _ = self.dataImportSplash {
|
||||
self.dataImportSplash = nil
|
||||
self.mainWindow.coveringView = nil
|
||||
}
|
||||
}
|
||||
if let temporaryId = temporaryId {
|
||||
Queue.mainQueue().after(1.0, {
|
||||
let statusPath = appGroupUrl.path + "/Documents/importcompleted"
|
||||
let _ = try? FileManager.default.createDirectory(atPath: appGroupUrl.path + "/Documents", withIntermediateDirectories: true, attributes: nil)
|
||||
let _ = try? Data().write(to: URL(fileURLWithPath: statusPath))
|
||||
})
|
||||
return sharedContext.accountManager.transaction { transaction -> SharedAccountContext in
|
||||
transaction.setCurrentId(temporaryId)
|
||||
transaction.updateRecord(temporaryId, { record in
|
||||
if let record = record {
|
||||
return AccountRecord(id: record.id, attributes: record.attributes, temporarySessionId: nil)
|
||||
}
|
||||
return record
|
||||
})
|
||||
return sharedContext
|
||||
}
|
||||
} else {
|
||||
return .single(sharedContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let watchManagerArgumentsPromise = Promise<WatchManagerArguments?>()
|
||||
|
||||
let replyFromNotificationsActive = self.replyFromNotificationsTokensPromise.get()
|
||||
|> map {
|
||||
!$0.isEmpty
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|
||||
let backgroundAudioActive = self.hasActiveAudioSession.get()
|
||||
|> distinctUntilChanged
|
||||
|
||||
self.context.set(self.sharedContextPromise.get()
|
||||
|> deliverOnMainQueue
|
||||
|> mapToSignal { sharedContext -> Signal<ApplicationContext?, NoError> in
|
||||
return sharedContext.activeAccounts
|
||||
|> map { primary, _, auth -> (AnyObject?, Bool) in
|
||||
return (auth ?? primary, primary != nil)
|
||||
}
|
||||
|> distinctUntilChanged(isEqual: { lhs, rhs in
|
||||
if lhs.0 !== rhs.0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|> mapToSignal { account, hasOther -> Signal<(AnyObject, InitialPresentationDataAndSettings, Bool)?, NoError> in
|
||||
if let account = account as? Account {
|
||||
return currentPresentationDataAndSettings(postbox: account.postbox)
|
||||
|> map { initialSettings in
|
||||
return (account, initialSettings, hasOther)
|
||||
}
|
||||
} else if let account = account as? UnauthorizedAccount {
|
||||
return currentPresentationDataAndSettings(postbox: account.postbox)
|
||||
|> map { initialSettings in
|
||||
return (account, initialSettings, hasOther)
|
||||
}
|
||||
} else {
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
|> deliverOnMainQueue
|
||||
|> map { accountAndSettings -> ApplicationContext? in
|
||||
return accountAndSettings.flatMap { account, initialSettings, hasOther in
|
||||
if let account = account as? Account {
|
||||
let context = AccountContext(sharedContext: sharedContext, account: account, initialPresentationDataAndSettings: initialSettings)
|
||||
return ApplicationContext.authorized(AuthorizedApplicationContext(mainWindow: self.mainWindow, replyFromNotificationsActive: replyFromNotificationsActive, backgroundAudioActive: backgroundAudioActive, watchManagerArguments: watchManagerArgumentsPromise.get(), context: context, accountManager: sharedContext.accountManager, legacyBasePath: appGroupUrl.path, showCallsTab: initialSettings.callListSettings.showTab, reinitializedNotificationSettings: {
|
||||
let _ = (self.context.get()
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { value in
|
||||
if let value = value, case let .authorized(context) = value {
|
||||
self.registerForNotifications(context: context.context, authorize: false)
|
||||
}
|
||||
})
|
||||
}))
|
||||
} else if let account = account as? UnauthorizedAccount {
|
||||
return ApplicationContext.unauthorized(UnauthorizedApplicationContext(sharedContext: sharedContext, account: account, hasOtherAccounts: hasOther))
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let contextReadyDisposable = MetaDisposable()
|
||||
@ -695,8 +733,6 @@ private enum QueuedWakeup: Int32 {
|
||||
network = unauthorized.account.network
|
||||
case let .authorized(authorized):
|
||||
network = authorized.context.account.network
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -712,8 +748,6 @@ private enum QueuedWakeup: Int32 {
|
||||
authorized.context.account.shouldKeepOnlinePresence.set(.single(false))
|
||||
authorized.context.account.shouldExplicitelyKeepWorkerConnections.set(.single(false))
|
||||
authorized.context.account.shouldKeepBackgroundDownloadConnections.set(.single(false))
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
self.contextValue = context
|
||||
@ -743,14 +777,13 @@ private enum QueuedWakeup: Int32 {
|
||||
authorizeNotifications = false
|
||||
}
|
||||
self.registerForNotifications(context: context.context, authorize: authorizeNotifications)
|
||||
context.context.account.notificationToken.set(self.notificationTokenPromise.get())
|
||||
context.context.account.voipToken.set(self.voipTokenPromise.get())
|
||||
case .unauthorized:
|
||||
break
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
self.mainWindow.viewController = nil
|
||||
self.mainWindow.topLevelOverlayControllers = []
|
||||
contextReadyDisposable.set(nil)
|
||||
}
|
||||
}))
|
||||
@ -1311,8 +1344,6 @@ private enum QueuedWakeup: Int32 {
|
||||
} else if let confirmationCode = parseConfirmationCodeUrl(url) {
|
||||
context.rootController.applyConfirmationCode(confirmationCode)
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -1324,7 +1355,7 @@ private enum QueuedWakeup: Int32 {
|
||||
if let handle = contact.personHandle?.value {
|
||||
if let userId = Int32(handle) {
|
||||
if let contextValue = self.contextValue, case let .authorized(context) = contextValue {
|
||||
let _ = context.context.callManager?.requestCall(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), endCurrentIfAny: false)
|
||||
let _ = context.context.callManager?.requestCall(account: context.context.account, peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), endCurrentIfAny: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1582,9 +1613,9 @@ private enum QueuedWakeup: Int32 {
|
||||
context.wakeupManager.wakeupForIncomingMessages(completion: { messageIds -> Signal<Void, NoError> in
|
||||
if let contextValue = self.contextValue, case let .authorized(context) = contextValue {
|
||||
if handleVoipNotifications {
|
||||
return context.notificationManager.commitRemoteNotification(originalRequestId: requestId, messageIds: messageIds)
|
||||
return context.notificationManager.commitRemoteNotification(context: context.context, originalRequestId: requestId, messageIds: messageIds)
|
||||
} else {
|
||||
return context.notificationManager.commitRemoteNotification(originalRequestId: nil, messageIds: [])
|
||||
return context.notificationManager.commitRemoteNotification(context: context.context, originalRequestId: nil, messageIds: [])
|
||||
}
|
||||
} else {
|
||||
Logger.shared.log("App \(self.episodeId)", "Couldn't process remote notifications wakeup result")
|
||||
|
||||
@ -7,7 +7,7 @@ import TelegramCore
|
||||
import Display
|
||||
import LegacyComponents
|
||||
|
||||
func applicationContext(networkArguments: NetworkInitializationArguments, applicationBindings: TelegramApplicationBindings, replyFromNotificationsActive: Signal<Bool, NoError>, backgroundAudioActive: Signal<Bool, NoError>, watchManagerArguments: Signal<WatchManagerArguments?, NoError>, accountManager: AccountManager, rootPath: String, legacyBasePath: String, mainWindow: Window1, reinitializedNotificationSettings: @escaping () -> Void) -> Signal<ApplicationContext?, NoError> {
|
||||
/*func applicationContext(networkArguments: NetworkInitializationArguments, applicationBindings: TelegramApplicationBindings, replyFromNotificationsActive: Signal<Bool, NoError>, backgroundAudioActive: Signal<Bool, NoError>, watchManagerArguments: Signal<WatchManagerArguments?, NoError>, sharedContext: SharedAccountContext, accountManager: AccountManager, rootPath: String, legacyBasePath: String, mainWindow: Window1, reinitializedNotificationSettings: @escaping () -> Void) -> Signal<ApplicationContext?, NoError> {
|
||||
return currentAccount(allocateIfNotExists: true, networkArguments: networkArguments, supplementary: false, manager: accountManager, rootPath: rootPath, auxiliaryMethods: telegramAccountAuxiliaryMethods)
|
||||
|> filter { $0 != nil }
|
||||
|> deliverOnMainQueue
|
||||
@ -26,14 +26,14 @@ func applicationContext(networkArguments: NetworkInitializationArguments, applic
|
||||
return currentPresentationDataAndSettings(postbox: account.postbox)
|
||||
|> deliverOnMainQueue
|
||||
|> map { dataAndSettings -> ApplicationContext? in
|
||||
return .authorized(AuthorizedApplicationContext(mainWindow: mainWindow, replyFromNotificationsActive: replyFromNotificationsActive, backgroundAudioActive: backgroundAudioActive, watchManagerArguments: watchManagerArguments, context: AccountContext(account: account, applicationBindings: applicationBindings, accountManager: accountManager, initialPresentationDataAndSettings: dataAndSettings, postbox: account.postbox), accountManager: accountManager, legacyBasePath: legacyBasePath, showCallsTab: dataAndSettings.callListSettings.showTab, reinitializedNotificationSettings: reinitializedNotificationSettings))
|
||||
return .authorized(AuthorizedApplicationContext(mainWindow: mainWindow, replyFromNotificationsActive: replyFromNotificationsActive, backgroundAudioActive: backgroundAudioActive, watchManagerArguments: watchManagerArguments, context: AccountContext(sharedContext: sharedContext, account: account, initialPresentationDataAndSettings: dataAndSettings), accountManager: accountManager, legacyBasePath: legacyBasePath, showCallsTab: dataAndSettings.callListSettings.showTab, reinitializedNotificationSettings: reinitializedNotificationSettings))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
func isAccessLocked(data: PostboxAccessChallengeData, at timestamp: Int32) -> Bool {
|
||||
if data.isLockable, let autolockDeadline = data.autolockDeadline, autolockDeadline <= timestamp {
|
||||
@ -85,18 +85,20 @@ enum ApplicationContext {
|
||||
}
|
||||
|
||||
final class UnauthorizedApplicationContext {
|
||||
let sharedContext: SharedAccountContext
|
||||
let account: UnauthorizedAccount
|
||||
var strings: PresentationStrings
|
||||
|
||||
let rootController: AuthorizationSequenceController
|
||||
|
||||
init(account: UnauthorizedAccount, applicationBindings: TelegramApplicationBindings) {
|
||||
init(sharedContext: SharedAccountContext, account: UnauthorizedAccount, hasOtherAccounts: Bool) {
|
||||
self.sharedContext = sharedContext
|
||||
self.account = account
|
||||
self.strings = defaultPresentationStrings
|
||||
|
||||
self.rootController = AuthorizationSequenceController(account: account, strings: self.strings, openUrl: applicationBindings.openUrl, apiId: BuildConfig.shared().apiId, apiHash: BuildConfig.shared().apiHash)
|
||||
self.rootController = AuthorizationSequenceController(sharedContext: sharedContext, account: account, hasOtherAccounts: hasOtherAccounts, strings: self.strings, openUrl: sharedContext.applicationBindings.openUrl, apiId: BuildConfig.shared().apiId, apiHash: BuildConfig.shared().apiHash)
|
||||
|
||||
account.shouldBeServiceTaskMaster.set(applicationBindings.applicationInForeground |> map { value -> AccountServiceTaskMasterMode in
|
||||
account.shouldBeServiceTaskMaster.set(sharedContext.applicationBindings.applicationInForeground |> map { value -> AccountServiceTaskMasterMode in
|
||||
if value {
|
||||
return .always
|
||||
} else {
|
||||
@ -234,13 +236,12 @@ final class AuthorizedApplicationContext {
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|
||||
self.wakeupManager = WakeupManager(inForeground: context.applicationBindings.applicationInForeground, runningServiceTasks: context.account.importantTasksRunning, runningBackgroundLocationTasks: runningBackgroundLocationTasks, runningWatchTasks: runningWatchTasksPromise.get(), runningDownloadTasks: runningDownloadTasks)
|
||||
self.wakeupManager = WakeupManager(inForeground: context.sharedContext.applicationBindings.applicationInForeground, runningServiceTasks: context.account.importantTasksRunning, runningBackgroundLocationTasks: runningBackgroundLocationTasks, runningWatchTasks: runningWatchTasksPromise.get(), runningDownloadTasks: runningDownloadTasks)
|
||||
self.wakeupManager.account = context.account
|
||||
|
||||
self.showCallsTab = showCallsTab
|
||||
|
||||
self.notificationManager = NotificationManager()
|
||||
self.notificationManager.context = context
|
||||
self.notificationManager.isApplicationInForeground = false
|
||||
|
||||
self.overlayMediaController = OverlayMediaController()
|
||||
@ -254,11 +255,11 @@ final class AuthorizedApplicationContext {
|
||||
}, {
|
||||
openSettingsImpl?()
|
||||
})
|
||||
}, networkType: context.account.networkType, audioSession: context.mediaManager.audioSession, callSessionManager: context.account.callSessionManager)
|
||||
}, networkType: context.account.networkType, audioSession: context.sharedContext.mediaManager.audioSession, activeAccounts: .single([context.account]))
|
||||
context.callManager = callManager
|
||||
context.hasOngoingCall = self.hasOngoingCall.get()
|
||||
|
||||
let shouldBeServiceTaskMaster = combineLatest(context.applicationBindings.applicationInForeground, self.wakeupManager.isWokenUp, replyFromNotificationsActive, backgroundAudioActive, callManager.hasActiveCalls)
|
||||
let shouldBeServiceTaskMaster = combineLatest(context.sharedContext.applicationBindings.applicationInForeground, self.wakeupManager.isWokenUp, replyFromNotificationsActive, backgroundAudioActive, callManager.hasActiveCalls)
|
||||
|> map { foreground, wokenUp, replyFromNotificationsActive, backgroundAudioActive, hasActiveCalls -> AccountServiceTaskMasterMode in
|
||||
if foreground || wokenUp || replyFromNotificationsActive || hasActiveCalls {
|
||||
return .always
|
||||
@ -288,7 +289,7 @@ final class AuthorizedApplicationContext {
|
||||
})
|
||||
context.account.shouldExplicitelyKeepWorkerConnections.set(backgroundAudioActive)
|
||||
context.account.shouldKeepBackgroundDownloadConnections.set(context.fetchManager.hasUserInitiatedEntries)
|
||||
context.account.shouldKeepOnlinePresence.set(context.applicationBindings.applicationInForeground)
|
||||
context.account.shouldKeepOnlinePresence.set(context.sharedContext.applicationBindings.applicationInForeground)
|
||||
|
||||
let cache = TGCache(cachesPath: legacyBasePath + "/Caches")!
|
||||
|
||||
@ -324,7 +325,7 @@ final class AuthorizedApplicationContext {
|
||||
context.keyShortcutsController = keyShortcutsController
|
||||
}
|
||||
|
||||
self.applicationInForegroundDisposable = context.applicationBindings.applicationInForeground.start(next: { [weak self] value in
|
||||
self.applicationInForegroundDisposable = context.sharedContext.applicationBindings.applicationInForeground.start(next: { [weak self] value in
|
||||
Queue.mainQueue().async {
|
||||
self?.notificationManager.isApplicationInForeground = value
|
||||
}
|
||||
@ -372,14 +373,14 @@ final class AuthorizedApplicationContext {
|
||||
self?.mainWindow.present(c, on: .root)
|
||||
}
|
||||
openSettingsImpl = { [weak context] in
|
||||
context?.applicationBindings.openSettings()
|
||||
context?.sharedContext.applicationBindings.openSettings()
|
||||
}
|
||||
|
||||
let previousPasscodeState = Atomic<PasscodeState?>(value: nil)
|
||||
|
||||
let preferencesKey: PostboxViewKey = .preferences(keys: Set<ValueBoxKey>([ApplicationSpecificPreferencesKeys.presentationPasscodeSettings]))
|
||||
|
||||
self.passcodeStatusDisposable.set((combineLatest(queue: Queue.mainQueue(), context.account.postbox.combinedView(keys: [.accessChallengeData, preferencesKey]), context.applicationBindings.applicationIsActive)
|
||||
self.passcodeStatusDisposable.set((combineLatest(queue: Queue.mainQueue(), context.account.postbox.combinedView(keys: [.accessChallengeData, preferencesKey]), context.sharedContext.applicationBindings.applicationIsActive)
|
||||
|> map { view, isActive -> (PostboxAccessChallengeData, PresentationPasscodeSettings?, Bool) in
|
||||
let accessChallengeData = (view.views[.accessChallengeData] as? AccessChallengeDataView)?.data ?? PostboxAccessChallengeData.none
|
||||
let passcodeSettings = (view.views[preferencesKey] as! PreferencesView).values[ApplicationSpecificPreferencesKeys.presentationPasscodeSettings] as? PresentationPasscodeSettings
|
||||
@ -669,11 +670,20 @@ final class AuthorizedApplicationContext {
|
||||
}
|
||||
|
||||
if !strongSelf.isLocked {
|
||||
if inAppNotificationSettings.playSounds {
|
||||
serviceSoundManager.playIncomingMessageSound()
|
||||
}
|
||||
if inAppNotificationSettings.vibrate {
|
||||
serviceSoundManager.playVibrationSound()
|
||||
let isMuted = firstMessage.attributes.contains(where: { attribute in
|
||||
if let attribute = attribute as? NotificationInfoMessageAttribute {
|
||||
return attribute.flags.contains(.muted)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
if !isMuted {
|
||||
if inAppNotificationSettings.playSounds {
|
||||
serviceSoundManager.playIncomingMessageSound()
|
||||
}
|
||||
if inAppNotificationSettings.vibrate {
|
||||
serviceSoundManager.playVibrationSound()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -913,7 +923,8 @@ final class AuthorizedApplicationContext {
|
||||
}))
|
||||
}
|
||||
|
||||
self.displayAlertsDisposable = (context.account.stateManager.displayAlerts |> deliverOnMainQueue).start(next: { [weak self] alerts in
|
||||
self.displayAlertsDisposable = (context.account.stateManager.displayAlerts
|
||||
|> deliverOnMainQueue).start(next: { [weak self] alerts in
|
||||
if let strongSelf = self{
|
||||
for text in alerts {
|
||||
let presentationData = strongSelf.context.currentPresentationData.with { $0 }
|
||||
@ -926,7 +937,7 @@ final class AuthorizedApplicationContext {
|
||||
self.removeNotificationsDisposable = (context.account.stateManager.appliedIncomingReadMessages
|
||||
|> deliverOnMainQueue).start(next: { [weak self] ids in
|
||||
if let strongSelf = self {
|
||||
strongSelf.context.applicationBindings.clearMessageNotifications(ids)
|
||||
strongSelf.context.sharedContext.applicationBindings.clearMessageNotifications(ids)
|
||||
}
|
||||
})
|
||||
|
||||
@ -946,11 +957,11 @@ final class AuthorizedApplicationContext {
|
||||
strongSelf.callState.set(call.state
|
||||
|> map(Optional.init))
|
||||
strongSelf.hasOngoingCall.set(true)
|
||||
strongSelf.notificationManager.notificationCall = call
|
||||
strongSelf.notificationManager.setNotificationCall(call, strings: strongSelf.context.currentPresentationData.with({ $0 }).strings)
|
||||
} else {
|
||||
strongSelf.callState.set(.single(nil))
|
||||
strongSelf.hasOngoingCall.set(false)
|
||||
strongSelf.notificationManager.notificationCall = nil
|
||||
strongSelf.notificationManager.setNotificationCall(nil, strings: strongSelf.context.currentPresentationData.with({ $0 }).strings)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1004,7 +1015,7 @@ final class AuthorizedApplicationContext {
|
||||
self.context.account.resetStateManagement()
|
||||
let contactSynchronizationPreferencesKey = PostboxViewKey.preferences(keys: Set([ApplicationSpecificPreferencesKeys.contactSynchronizationSettings]))
|
||||
|
||||
let importableContacts = self.context.contactDataManager.importable()
|
||||
let importableContacts = self.context.sharedContext.contactDataManager?.importable() ?? .single([:])
|
||||
self.context.account.importableContacts.set(self.context.account.postbox.combinedView(keys: [contactSynchronizationPreferencesKey])
|
||||
|> mapToSignal { preferences -> Signal<[DeviceContactNormalizedPhoneNumber: ImportableDeviceContactData], NoError> in
|
||||
let settings: ContactSynchronizationSettings = ((preferences.views[contactSynchronizationPreferencesKey] as? PreferencesView)?.values[ApplicationSpecificPreferencesKeys.contactSynchronizationSettings] as? ContactSynchronizationSettings) ?? .defaultSettings
|
||||
@ -1054,7 +1065,7 @@ final class AuthorizedApplicationContext {
|
||||
strongSelf.context.watchManager = watchManager
|
||||
runningWatchTasksPromise.set(watchManager.runningTasks)
|
||||
|
||||
strongSelf.watchNavigateToMessageDisposable.set((strongSelf.context.applicationBindings.applicationInForeground |> mapToSignal({ applicationInForeground -> Signal<(Bool, MessageId), NoError> in
|
||||
strongSelf.watchNavigateToMessageDisposable.set((strongSelf.context.sharedContext.applicationBindings.applicationInForeground |> mapToSignal({ applicationInForeground -> Signal<(Bool, MessageId), NoError> in
|
||||
return watchManager.navigateToMessageRequested
|
||||
|> map { messageId in
|
||||
return (applicationInForeground, messageId)
|
||||
@ -1080,7 +1091,7 @@ final class AuthorizedApplicationContext {
|
||||
(strongSelf.rootController.viewControllers.last as? ViewController)?.present(controller, in: .window(.root))
|
||||
}
|
||||
} else {
|
||||
strongSelf.notificationManager.presentWatchContinuityNotification(messageId: messageId)
|
||||
strongSelf.notificationManager.presentWatchContinuityNotification(context: strongSelf.context, messageId: messageId)
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
@ -44,32 +44,6 @@ enum NotificationManagedNotificationRequestId: Hashable {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var hashValue: Int {
|
||||
switch self {
|
||||
case let .messageId(messageId):
|
||||
return messageId.id.hashValue
|
||||
case let .globallyUniqueId(id, _):
|
||||
return id.hashValue
|
||||
}
|
||||
}
|
||||
|
||||
static func ==(lhs: NotificationManagedNotificationRequestId, rhs: NotificationManagedNotificationRequestId) -> Bool {
|
||||
switch lhs {
|
||||
case let .messageId(id):
|
||||
if case .messageId(id) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .globallyUniqueId(id, peerId):
|
||||
if case .globallyUniqueId(id, peerId) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func processedSoundName(_ name: String) -> String {
|
||||
@ -83,7 +57,7 @@ private func processedSoundName(_ name: String) -> String {
|
||||
final class NotificationManager {
|
||||
private var processedMessages = Set<MessageId>()
|
||||
|
||||
var context: AccountContext? {
|
||||
/*var context: AccountContext? {
|
||||
didSet {
|
||||
assert(Queue.mainQueue().isCurrent())
|
||||
|
||||
@ -103,17 +77,19 @@ final class NotificationManager {
|
||||
self.notificationMessagesDisposable.set(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
private let notificationCallStateDisposable = MetaDisposable()
|
||||
var notificationCall: PresentationCall? {
|
||||
didSet {
|
||||
if self.notificationCall?.internalId != oldValue?.internalId {
|
||||
if let notificationCall = self.notificationCall {
|
||||
let peer = notificationCall.peer
|
||||
let internalId = notificationCall.internalId
|
||||
let isIntegratedWithCallKit = notificationCall.isIntegratedWithCallKit
|
||||
self.notificationCallStateDisposable.set((notificationCall.state
|
||||
private(set) var notificationCall: PresentationCall?
|
||||
|
||||
func setNotificationCall(_ call: PresentationCall?, strings: PresentationStrings) {
|
||||
if self.notificationCall?.internalId != call?.internalId {
|
||||
self.notificationCall = call
|
||||
if let notificationCall = self.notificationCall {
|
||||
let peer = notificationCall.peer
|
||||
let internalId = notificationCall.internalId
|
||||
let isIntegratedWithCallKit = notificationCall.isIntegratedWithCallKit
|
||||
self.notificationCallStateDisposable.set((notificationCall.state
|
||||
|> map { state -> (Peer?, CallSessionInternalId)? in
|
||||
if isIntegratedWithCallKit {
|
||||
return nil
|
||||
@ -125,12 +101,11 @@ final class NotificationManager {
|
||||
}
|
||||
}
|
||||
|> distinctUntilChanged(isEqual: { $0?.1 == $1?.1 })).start(next: { [weak self] peerAndInternalId in
|
||||
self?.updateNotificationCall(call: peerAndInternalId)
|
||||
self?.updateNotificationCall(call: peerAndInternalId, strings: strings)
|
||||
}))
|
||||
} else {
|
||||
self.notificationCallStateDisposable.set(nil)
|
||||
self.updateNotificationCall(call: nil)
|
||||
}
|
||||
} else {
|
||||
self.notificationCallStateDisposable.set(nil)
|
||||
self.updateNotificationCall(call: nil, strings: strings)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -264,98 +239,90 @@ final class NotificationManager {
|
||||
}
|
||||
}
|
||||
|
||||
func commitRemoteNotification(originalRequestId: NotificationManagedNotificationRequestId?, messageIds: [MessageId]) -> Signal<Void, NoError> {
|
||||
if let context = self.context {
|
||||
return context.account.postbox.transaction { transaction -> ([(MessageId, [Message], Bool, PeerMessageSound, Bool)], Bool) in
|
||||
var isLocked = false
|
||||
if isAccessLocked(data: transaction.getAccessChallengeData(), at: Int32(CFAbsoluteTimeGetCurrent())) {
|
||||
isLocked = true
|
||||
}
|
||||
|
||||
var results: [(MessageId, [Message], Bool, PeerMessageSound, Bool)] = []
|
||||
var updatedMessageIds = messageIds
|
||||
if let originalRequestId = originalRequestId {
|
||||
switch originalRequestId {
|
||||
case let .messageId(id):
|
||||
if !updatedMessageIds.contains(id) {
|
||||
updatedMessageIds.append(id)
|
||||
}
|
||||
case .globallyUniqueId:
|
||||
break
|
||||
}
|
||||
}
|
||||
for id in updatedMessageIds {
|
||||
let (messages, notify, sound, displayContents) = messagesForNotification(transaction: transaction, id: id, alwaysReturnMessage: true)
|
||||
|
||||
if results.contains(where: { result in
|
||||
return result.1.contains(where: { message in
|
||||
return messages.contains(where: {
|
||||
message.id == $0.id
|
||||
})
|
||||
})
|
||||
}) {
|
||||
continue
|
||||
}
|
||||
results.append((id, messages, notify, sound, displayContents))
|
||||
}
|
||||
return (results, isLocked)
|
||||
func commitRemoteNotification(context: AccountContext, originalRequestId: NotificationManagedNotificationRequestId?, messageIds: [MessageId]) -> Signal<Void, NoError> {
|
||||
return context.account.postbox.transaction { transaction -> ([(MessageId, [Message], Bool, PeerMessageSound, Bool)], Bool) in
|
||||
var isLocked = false
|
||||
if isAccessLocked(data: transaction.getAccessChallengeData(), at: Int32(CFAbsoluteTimeGetCurrent())) {
|
||||
isLocked = true
|
||||
}
|
||||
|> deliverOnMainQueue
|
||||
|> beforeNext {
|
||||
[weak self] results, isLocked in
|
||||
if let strongSelf = self {
|
||||
let delayUntilTimestamp: Int32 = strongSelf.context?.account.stateManager.getDelayNotificatonsUntil() ?? 0
|
||||
|
||||
for (id, messages, notify, sound, displayContents) in results {
|
||||
let requestId: NotificationManagedNotificationRequestId = .messageId(id)
|
||||
if let message = messages.first, message.id.peerId.namespace != Namespaces.Peer.SecretChat, !strongSelf.processedRequestIds.contains(requestId) {
|
||||
let notificationRequestTimeout = strongSelf.notificationRequests[requestId]
|
||||
if notificationRequestTimeout == nil || CFAbsoluteTimeGetCurrent() < notificationRequestTimeout! {
|
||||
if #available(iOS 10.0, *) {
|
||||
let center = UNUserNotificationCenter.current()
|
||||
center.removePendingNotificationRequests(withIdentifiers: [notificationKey(requestId)])
|
||||
} else {
|
||||
let key = notificationKey(requestId)
|
||||
if let notifications = UIApplication.shared.scheduledLocalNotifications {
|
||||
for notification in notifications {
|
||||
if let userInfo = notification.userInfo, let id = userInfo["id"] as? String {
|
||||
if id == key {
|
||||
UIApplication.shared.cancelLocalNotification(notification)
|
||||
break
|
||||
}
|
||||
|
||||
var results: [(MessageId, [Message], Bool, PeerMessageSound, Bool)] = []
|
||||
var updatedMessageIds = messageIds
|
||||
if let originalRequestId = originalRequestId {
|
||||
switch originalRequestId {
|
||||
case let .messageId(id):
|
||||
if !updatedMessageIds.contains(id) {
|
||||
updatedMessageIds.append(id)
|
||||
}
|
||||
case .globallyUniqueId:
|
||||
break
|
||||
}
|
||||
}
|
||||
for id in updatedMessageIds {
|
||||
let (messages, notify, sound, displayContents) = messagesForNotification(transaction: transaction, id: id, alwaysReturnMessage: true)
|
||||
|
||||
if results.contains(where: { result in
|
||||
return result.1.contains(where: { message in
|
||||
return messages.contains(where: {
|
||||
message.id == $0.id
|
||||
})
|
||||
})
|
||||
}) {
|
||||
continue
|
||||
}
|
||||
results.append((id, messages, notify, sound, displayContents))
|
||||
}
|
||||
return (results, isLocked)
|
||||
}
|
||||
|> deliverOnMainQueue
|
||||
|> beforeNext {
|
||||
[weak self] results, isLocked in
|
||||
if let strongSelf = self {
|
||||
let delayUntilTimestamp: Int32 = context.account.stateManager.getDelayNotificatonsUntil() ?? 0
|
||||
|
||||
for (id, messages, notify, sound, displayContents) in results {
|
||||
let requestId: NotificationManagedNotificationRequestId = .messageId(id)
|
||||
if let message = messages.first, message.id.peerId.namespace != Namespaces.Peer.SecretChat, !strongSelf.processedRequestIds.contains(requestId) {
|
||||
let notificationRequestTimeout = strongSelf.notificationRequests[requestId]
|
||||
if notificationRequestTimeout == nil || CFAbsoluteTimeGetCurrent() < notificationRequestTimeout! {
|
||||
if #available(iOS 10.0, *) {
|
||||
let center = UNUserNotificationCenter.current()
|
||||
center.removePendingNotificationRequests(withIdentifiers: [notificationKey(requestId)])
|
||||
} else {
|
||||
let key = notificationKey(requestId)
|
||||
if let notifications = UIApplication.shared.scheduledLocalNotifications {
|
||||
for notification in notifications {
|
||||
if let userInfo = notification.userInfo, let id = userInfo["id"] as? String {
|
||||
if id == key {
|
||||
UIApplication.shared.cancelLocalNotification(notification)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !strongSelf.processedRequestIds.contains(requestId) {
|
||||
strongSelf.processedRequestIds.insert(requestId)
|
||||
|
||||
if !strongSelf.processedRequestIds.contains(requestId) {
|
||||
strongSelf.processedRequestIds.insert(requestId)
|
||||
|
||||
if notify {
|
||||
var delayMessage = false
|
||||
if message.timestamp <= delayUntilTimestamp && message.id.peerId.namespace != Namespaces.Peer.SecretChat {
|
||||
delayMessage = true
|
||||
}
|
||||
strongSelf.processNotificationMessages([(messages, sound, displayContents, delayMessage)], isLocked: isLocked)
|
||||
if notify {
|
||||
var delayMessage = false
|
||||
if message.timestamp <= delayUntilTimestamp && message.id.peerId.namespace != Namespaces.Peer.SecretChat {
|
||||
delayMessage = true
|
||||
}
|
||||
strongSelf.processNotificationMessages(context: context, messageList: [(messages, sound, displayContents, delayMessage)], isLocked: isLocked)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} |> map { _ in
|
||||
return Void()
|
||||
}
|
||||
} else {
|
||||
return .complete()
|
||||
} |> map { _ in
|
||||
return Void()
|
||||
}
|
||||
}
|
||||
|
||||
private func processNotificationMessages(_ messageList: [([Message], PeerMessageSound, Bool, Bool)], isLocked: Bool) {
|
||||
guard let context = self.context else {
|
||||
Logger.shared.log("NotificationManager", "context missing")
|
||||
return
|
||||
}
|
||||
private func processNotificationMessages(context: AccountContext, messageList: [([Message], PeerMessageSound, Bool, Bool)], isLocked: Bool) {
|
||||
let presentationData = (context.currentPresentationData.with { $0 })
|
||||
let strings = presentationData.strings
|
||||
let nameDisplayOrder = presentationData.nameDisplayOrder
|
||||
@ -554,7 +521,7 @@ final class NotificationManager {
|
||||
loop: for media in firstMessage.media {
|
||||
if let image = media as? TelegramMediaImage {
|
||||
mediaRepresentations = image.representations
|
||||
if !firstMessage.containsSecretMedia, let context = self.context, let smallest = smallestImageRepresentation(image.representations), let largest = largestImageRepresentation(image.representations) {
|
||||
if !firstMessage.containsSecretMedia, let smallest = smallestImageRepresentation(image.representations), let largest = largestImageRepresentation(image.representations) {
|
||||
var imageInfo: [String: Any] = [:]
|
||||
|
||||
var thumbnailInfo: [String: Any] = [:]
|
||||
@ -675,7 +642,7 @@ final class NotificationManager {
|
||||
content.threadIdentifier = "peer_\(firstMessage.id.peerId.toInt64())"
|
||||
|
||||
if mediaInfo != nil, let mediaRepresentations = mediaRepresentations {
|
||||
if let context = self.context, let smallest = smallestImageRepresentation(mediaRepresentations) {
|
||||
if let smallest = smallestImageRepresentation(mediaRepresentations) {
|
||||
/*if let path = account.postbox.mediaBox.completedResourcePath(smallest.resource) {
|
||||
var randomId: Int64 = 0
|
||||
arc4random_buf(&randomId, 8)
|
||||
@ -752,7 +719,7 @@ final class NotificationManager {
|
||||
|
||||
private var currentNotificationCall: (peer: Peer?, internalId: CallSessionInternalId)?
|
||||
|
||||
private func updateNotificationCall(call: (peer: Peer?, internalId: CallSessionInternalId)?) {
|
||||
private func updateNotificationCall(call: (peer: Peer?, internalId: CallSessionInternalId)?, strings: PresentationStrings) {
|
||||
if let previousCall = currentNotificationCall {
|
||||
if #available(iOS 10.0, *) {
|
||||
let center = UNUserNotificationCenter.current()
|
||||
@ -769,14 +736,24 @@ final class NotificationManager {
|
||||
}
|
||||
self.currentNotificationCall = call
|
||||
|
||||
guard let context = self.context else {
|
||||
return
|
||||
}
|
||||
let presentationData = context.currentPresentationData.with { $0 }
|
||||
if let notificationCall = call {
|
||||
let rawText = strings.PUSH_PHONE_CALL_REQUEST(notificationCall.peer?.displayTitle ?? "").0
|
||||
let title: String?
|
||||
let body: String
|
||||
if let index = rawText.firstIndex(of: "|") {
|
||||
title = String(rawText[rawText.startIndex ..< index])
|
||||
body = String(rawText[rawText.index(after: index)...])
|
||||
} else {
|
||||
title = nil
|
||||
body = rawText
|
||||
}
|
||||
|
||||
if #available(iOS 10.0, *) {
|
||||
let content = UNMutableNotificationContent()
|
||||
content.body = presentationData.strings.PUSH_PHONE_CALL_REQUEST(notificationCall.peer?.displayTitle ?? "").0
|
||||
if let title = title {
|
||||
content.title = title
|
||||
}
|
||||
content.body = body
|
||||
content.sound = UNNotificationSound(named: "0.m4a")
|
||||
content.categoryIdentifier = "incomingCall"
|
||||
content.userInfo = [:]
|
||||
@ -793,7 +770,16 @@ final class NotificationManager {
|
||||
|
||||
} else {
|
||||
let notification = UILocalNotification()
|
||||
notification.alertBody = presentationData.strings.PUSH_PHONE_CALL_REQUEST(notificationCall.peer?.displayTitle ?? "").0
|
||||
if #available(iOS 8.2, *) {
|
||||
notification.alertTitle = title
|
||||
notification.alertBody = body
|
||||
} else {
|
||||
if let title = title {
|
||||
notification.alertBody = "\(title): \(body)"
|
||||
} else {
|
||||
notification.alertBody = body
|
||||
}
|
||||
}
|
||||
notification.category = "incomingCall"
|
||||
notification.userInfo = ["callId": String(describing: notificationCall.internalId)]
|
||||
notification.soundName = "0.m4a"
|
||||
@ -802,7 +788,7 @@ final class NotificationManager {
|
||||
}
|
||||
}
|
||||
|
||||
func presentWatchContinuityNotification(messageId: MessageId) {
|
||||
func presentWatchContinuityNotification(context: AccountContext, messageId: MessageId) {
|
||||
if #available(iOS 10.0, *) {
|
||||
let center = UNUserNotificationCenter.current()
|
||||
center.removeDeliveredNotifications(withIdentifiers: ["watch"])
|
||||
@ -815,9 +801,6 @@ final class NotificationManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
guard let context = self.context else {
|
||||
return
|
||||
}
|
||||
let presentationData = context.currentPresentationData.with { $0 }
|
||||
|
||||
var userInfo: [AnyHashable : Any] = [:]
|
||||
|
||||
@ -13,7 +13,8 @@ enum SnapshotEnvironmentTheme {
|
||||
}
|
||||
|
||||
func snapshotEnvironment(application: UIApplication, mainWindow: UIWindow, statusBarHost: StatusBarHost, theme: SnapshotEnvironmentTheme) -> (AccountContext, AccountManager) {
|
||||
var randomId: Int64 = 0
|
||||
preconditionFailure()
|
||||
/*var randomId: Int64 = 0
|
||||
arc4random_buf(&randomId, 8)
|
||||
let path = NSTemporaryDirectory() + "\(randomId)"
|
||||
|
||||
@ -106,9 +107,9 @@ func snapshotEnvironment(application: UIApplication, mainWindow: UIWindow, statu
|
||||
semaphore1.wait()
|
||||
precondition(dataAndSettings != nil)
|
||||
|
||||
let context = AccountContext(account: result!, applicationBindings: applicationBindings, accountManager: accountManagerValue!, initialPresentationDataAndSettings: dataAndSettings!, postbox: result!.postbox)
|
||||
let context = AccountContext(sharedContext: SharedAccountContext(applicationBindings: applicationBindings, accountManager: accountManagerValue!), account: result!, initialPresentationDataAndSettings: dataAndSettings!)
|
||||
|
||||
return (context, accountManagerValue!)
|
||||
return (context, accountManagerValue!)*/
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit bead1574a09c72ce8411938124c717180926789a
|
||||
Subproject commit 89531617a0b77014aa69dd8043b67858218e6a1c
|
||||
@ -1 +1 @@
|
||||
Subproject commit acbebf2342b6c374d3123ff31e82db1a7f5c9302
|
||||
Subproject commit f811d2a6475398acafae51f8b562b65d486b8bfd
|
||||
@ -1 +1 @@
|
||||
Subproject commit 1a4d2ae68067d781baaaa235ec6ac8fcd91ae13b
|
||||
Subproject commit e05c15c5903fb301aefd2b4952b5361c9dabc2f3
|
||||
@ -1 +1 @@
|
||||
Subproject commit 071c1c1f903d30c96a89a4708e5fc519d6310a6f
|
||||
Subproject commit 668207ab55d2e58843b0614260f7738c3d6116c4
|
||||
@ -1 +1 @@
|
||||
Subproject commit 062d0a48d60f6c8fb732227410bf6fe1d12ca456
|
||||
Subproject commit c1cc1f23b092a087d8af3b3a842dba1557568913
|
||||
@ -1 +1 @@
|
||||
Subproject commit a9d906d655fd337ab4d8f5e067e92a14c8837b77
|
||||
Subproject commit cc700e15e858cfa73ed67b9eaa09735681cc5491
|
||||
Loading…
x
Reference in New Issue
Block a user