mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 06:35:51 +00:00
Merge branch 'master' into holes
This commit is contained in:
@@ -8,28 +8,26 @@ variables:
|
|||||||
|
|
||||||
internal:
|
internal:
|
||||||
tags:
|
tags:
|
||||||
- ios
|
- ios_internal
|
||||||
stage: build
|
stage: build
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
except:
|
except:
|
||||||
- tags
|
- tags
|
||||||
script:
|
script:
|
||||||
- sh ~/ios-prepare-build.sh $CI_PROJECT_DIR/..
|
- sh buildbox/build-telegram.sh hockeyapp
|
||||||
- fastlane internalhockeyapp
|
|
||||||
environment:
|
environment:
|
||||||
name: internal
|
name: internal
|
||||||
|
|
||||||
beta_testflight:
|
beta_testflight:
|
||||||
tags:
|
tags:
|
||||||
- ios
|
- ios_beta
|
||||||
stage: build
|
stage: build
|
||||||
only:
|
only:
|
||||||
- beta
|
- beta
|
||||||
except:
|
except:
|
||||||
- tags
|
- tags
|
||||||
script:
|
script:
|
||||||
- sh ~/ios-prepare-build.sh $CI_PROJECT_DIR/..
|
- sh buildbox/build-telegram.sh appstore
|
||||||
- fastlane testflight_llc
|
|
||||||
environment:
|
environment:
|
||||||
name: testflight_llc
|
name: testflight_llc
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>XPC!</string>
|
<string>XPC!</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>5.5</string>
|
<string>5.5.1</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>${BUILD_NUMBER}</string>
|
<string>${BUILD_NUMBER}</string>
|
||||||
<key>NSExtension</key>
|
<key>NSExtension</key>
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
|
|||||||
|
|
||||||
let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown"
|
let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown"
|
||||||
|
|
||||||
sharedAccountContext = SharedAccountContext(mainWindow: nil, basePath: rootPath, accountManager: accountManager, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0, appData: BuildConfig.shared().bundleData), rootPath: rootPath, legacyBasePath: nil, legacyCache: nil, apsNotificationToken: .never(), voipNotificationToken: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _ in })
|
sharedAccountContext = SharedAccountContext(mainWindow: nil, basePath: rootPath, encryptionKey: BuildConfig.encryptionKey(rootPath), accountManager: accountManager, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0, appData: BuildConfig.shared().bundleData), rootPath: rootPath, legacyBasePath: nil, legacyCache: nil, apsNotificationToken: .never(), voipNotificationToken: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _ in })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>XPC!</string>
|
<string>XPC!</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>5.5</string>
|
<string>5.5.1</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>${BUILD_NUMBER}</string>
|
<string>${BUILD_NUMBER}</string>
|
||||||
<key>NSExtension</key>
|
<key>NSExtension</key>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>XPC!</string>
|
<string>XPC!</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>5.5</string>
|
<string>5.5.1</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>${BUILD_NUMBER}</string>
|
<string>${BUILD_NUMBER}</string>
|
||||||
<key>NSExtension</key>
|
<key>NSExtension</key>
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ class ShareRootController: UIViewController {
|
|||||||
})
|
})
|
||||||
semaphore.wait()
|
semaphore.wait()
|
||||||
|
|
||||||
let sharedContext = SharedAccountContext(mainWindow: nil, basePath: rootPath, accountManager: accountManager, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0, appData: BuildConfig.shared().bundleData), rootPath: rootPath, legacyBasePath: nil, legacyCache: nil, apsNotificationToken: .never(), voipNotificationToken: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _ in })
|
let sharedContext = SharedAccountContext(mainWindow: nil, basePath: rootPath, encryptionKey: BuildConfig.encryptionKey(rootPath), accountManager: accountManager, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0, appData: BuildConfig.shared().bundleData), rootPath: rootPath, legacyBasePath: nil, legacyCache: nil, apsNotificationToken: .never(), voipNotificationToken: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _ in })
|
||||||
sharedExtensionContext = SharedExtensionContext(sharedContext: sharedContext)
|
sharedExtensionContext = SharedExtensionContext(sharedContext: sharedContext)
|
||||||
globalSharedExtensionContext = sharedExtensionContext
|
globalSharedExtensionContext = sharedExtensionContext
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>XPC!</string>
|
<string>XPC!</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>5.5</string>
|
<string>5.5.1</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>${BUILD_NUMBER}</string>
|
<string>${BUILD_NUMBER}</string>
|
||||||
<key>NSExtension</key>
|
<key>NSExtension</key>
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag
|
|||||||
initializeAccountManagement()
|
initializeAccountManagement()
|
||||||
let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata")
|
let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata")
|
||||||
|
|
||||||
account = currentAccount(allocateIfNotExists: false, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0, appData: BuildConfig.shared().bundleData), supplementary: true, manager: accountManager, rootPath: rootPath, auxiliaryMethods: accountAuxiliaryMethods)
|
account = currentAccount(allocateIfNotExists: false, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0, appData: BuildConfig.shared().bundleData), supplementary: true, manager: accountManager, rootPath: rootPath, auxiliaryMethods: accountAuxiliaryMethods, encryptionKey: BuildConfig.encryptionKey(rootPath))
|
||||||
|> mapToSignal { account -> Signal<Account, NoError> in
|
|> mapToSignal { account -> Signal<Account, NoError> in
|
||||||
if let account = account {
|
if let account = account {
|
||||||
switch account {
|
switch account {
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ private enum QueuedWakeup: Int32 {
|
|||||||
case backgroundLocation
|
case backgroundLocation
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class SharedApplicationContext {
|
final class SharedApplicationContext {
|
||||||
let sharedContext: SharedAccountContext
|
let sharedContext: SharedAccountContext
|
||||||
let notificationManager: SharedNotificationManager
|
let notificationManager: SharedNotificationManager
|
||||||
let wakeupManager: SharedWakeupManager
|
let wakeupManager: SharedWakeupManager
|
||||||
@@ -372,6 +372,8 @@ private final class SharedApplicationContext {
|
|||||||
let rootPath = rootPathForBasePath(appGroupUrl.path)
|
let rootPath = rootPathForBasePath(appGroupUrl.path)
|
||||||
performAppGroupUpgrades(appGroupPath: appGroupUrl.path, rootPath: rootPath)
|
performAppGroupUpgrades(appGroupPath: appGroupUrl.path, rootPath: rootPath)
|
||||||
|
|
||||||
|
let encryptionKey = BuildConfig.encryptionKey(rootPath)
|
||||||
|
|
||||||
TempBox.initializeShared(basePath: rootPath, processType: "app", launchSpecificId: arc4random64())
|
TempBox.initializeShared(basePath: rootPath, processType: "app", launchSpecificId: arc4random64())
|
||||||
|
|
||||||
let logsPath = rootPath + "/logs"
|
let logsPath = rootPath + "/logs"
|
||||||
@@ -571,131 +573,154 @@ private final class SharedApplicationContext {
|
|||||||
self.window?.rootViewController?.dismiss(animated: true, completion: nil)
|
self.window?.rootViewController?.dismiss(animated: true, completion: nil)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Move back to signal
|
let accountManagerSignal = Signal<AccountManager, NoError> { subscriber in
|
||||||
let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata")
|
let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata")
|
||||||
let upgradeSemaphore = DispatchSemaphore(value: 0)
|
return upgradedAccounts(accountManager: accountManager, rootPath: rootPath, encryptionKey: encryptionKey).start(completed: {
|
||||||
let _ = upgradedAccounts(accountManager: accountManager, rootPath: rootPath).start(completed: {
|
subscriber.putNext(accountManager)
|
||||||
upgradeSemaphore.signal()
|
subscriber.putCompletion()
|
||||||
})
|
})
|
||||||
upgradeSemaphore.wait()
|
return EmptyDisposable
|
||||||
|
|
||||||
var initialPresentationDataAndSettings: InitialPresentationDataAndSettings?
|
|
||||||
let semaphore = DispatchSemaphore(value: 0)
|
|
||||||
let _ = currentPresentationDataAndSettings(accountManager: accountManager).start(next: { value in
|
|
||||||
initialPresentationDataAndSettings = value
|
|
||||||
semaphore.signal()
|
|
||||||
})
|
|
||||||
semaphore.wait()
|
|
||||||
|
|
||||||
let legacyBasePath = appGroupUrl.path
|
|
||||||
let legacyCache = LegacyCache(path: legacyBasePath + "/Caches")
|
|
||||||
|
|
||||||
var setPresentationCall: ((PresentationCall?) -> Void)?
|
|
||||||
let sharedContext = SharedAccountContext(mainWindow: self.mainWindow, basePath: rootPath, accountManager: accountManager, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: networkArguments, rootPath: rootPath, legacyBasePath: legacyBasePath, legacyCache: legacyCache, apsNotificationToken: self.notificationTokenPromise.get() |> map(Optional.init), voipNotificationToken: self.voipTokenPromise.get() |> map(Optional.init), setNotificationCall: { call in
|
|
||||||
setPresentationCall?(call)
|
|
||||||
}, navigateToChat: { accountId, peerId, messageId in
|
|
||||||
self.openChatWhenReady(accountId: accountId, peerId: peerId, messageId: messageId)
|
|
||||||
})
|
|
||||||
|
|
||||||
let rawAccounts = sharedContext.activeAccounts
|
|
||||||
|> map { _, accounts, _ -> [Account] in
|
|
||||||
return accounts.map({ $0.1 })
|
|
||||||
}
|
}
|
||||||
let _ = (sharedAccountInfos(accountManager: sharedContext.accountManager, accounts: rawAccounts)
|
|
||||||
|> deliverOn(Queue())).start(next: { infos in
|
|
||||||
storeAccountsData(rootPath: rootPath, accounts: infos)
|
|
||||||
})
|
|
||||||
|
|
||||||
sharedContext.presentGlobalController = { [weak self] c, a in
|
let sharedContextSignal = accountManagerSignal
|
||||||
guard let strongSelf = self else {
|
|> deliverOnMainQueue
|
||||||
return
|
|> mapToSignal { accountManager -> Signal<(SharedApplicationContext, LoggingSettings), NoError> in
|
||||||
}
|
var initialPresentationDataAndSettings: InitialPresentationDataAndSettings?
|
||||||
strongSelf.mainWindow.present(c, on: .root)
|
let semaphore = DispatchSemaphore(value: 0)
|
||||||
}
|
let _ = currentPresentationDataAndSettings(accountManager: accountManager).start(next: { value in
|
||||||
sharedContext.presentCrossfadeController = { [weak self] in
|
initialPresentationDataAndSettings = value
|
||||||
guard let strongSelf = self else {
|
semaphore.signal()
|
||||||
return
|
})
|
||||||
}
|
semaphore.wait()
|
||||||
var exists = false
|
|
||||||
strongSelf.mainWindow.forEachViewController { controller in
|
if let initialPresentationDataAndSettings = initialPresentationDataAndSettings {
|
||||||
if controller is ThemeSettingsCrossfadeController {
|
self.window?.backgroundColor = initialPresentationDataAndSettings.presentationData.theme.chatList.backgroundColor
|
||||||
exists = true
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !exists {
|
let legacyBasePath = appGroupUrl.path
|
||||||
strongSelf.mainWindow.present(ThemeSettingsCrossfadeController(), on: .root)
|
let legacyCache = LegacyCache(path: legacyBasePath + "/Caches")
|
||||||
}
|
|
||||||
}
|
var setPresentationCall: ((PresentationCall?) -> Void)?
|
||||||
|
let sharedContext = SharedAccountContext(mainWindow: self.mainWindow, basePath: rootPath, encryptionKey: encryptionKey, accountManager: accountManager, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: networkArguments, rootPath: rootPath, legacyBasePath: legacyBasePath, legacyCache: legacyCache, apsNotificationToken: self.notificationTokenPromise.get() |> map(Optional.init), voipNotificationToken: self.voipTokenPromise.get() |> map(Optional.init), setNotificationCall: { call in
|
||||||
let notificationManager = SharedNotificationManager(episodeId: self.episodeId, application: application, clearNotificationsManager: clearNotificationsManager, inForeground: applicationBindings.applicationInForeground, accounts: sharedContext.activeAccounts |> map { primary, accounts, _ in accounts.map({ ($0.1, $0.1.id == primary?.id) }) }, pollLiveLocationOnce: { accountId in
|
setPresentationCall?(call)
|
||||||
let _ = (self.context.get()
|
}, navigateToChat: { accountId, peerId, messageId in
|
||||||
|> filter {
|
self.openChatWhenReady(accountId: accountId, peerId: peerId, messageId: messageId)
|
||||||
return $0 != nil
|
}, displayUpgradeProgress: { progress in
|
||||||
}
|
if let progress = progress {
|
||||||
|> take(1)
|
if self.dataImportSplash == nil {
|
||||||
|> deliverOnMainQueue).start(next: { context in
|
self.dataImportSplash = LegacyDataImportSplash(theme: initialPresentationDataAndSettings?.presentationData.theme, strings: initialPresentationDataAndSettings?.presentationData.strings)
|
||||||
if let context = context, context.context.account.id == accountId {
|
self.mainWindow.coveringView = self.dataImportSplash
|
||||||
context.context.liveLocationManager?.pollOnce()
|
}
|
||||||
|
self.dataImportSplash?.progress = (.generic, progress)
|
||||||
|
} else if let dataImportSplash = self.dataImportSplash {
|
||||||
|
self.dataImportSplash = nil
|
||||||
|
if self.mainWindow.coveringView === dataImportSplash {
|
||||||
|
self.mainWindow.coveringView = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
|
||||||
setPresentationCall = { call in
|
let rawAccounts = sharedContext.activeAccounts
|
||||||
notificationManager.setNotificationCall(call, strings: sharedContext.currentPresentationData.with({ $0 }).strings)
|
|> map { _, accounts, _ -> [Account] in
|
||||||
}
|
return accounts.map({ $0.1 })
|
||||||
let liveLocationPolling = self.context.get()
|
}
|
||||||
|> mapToSignal { context -> Signal<AccountRecordId?, NoError> in
|
let _ = (sharedAccountInfos(accountManager: sharedContext.accountManager, accounts: rawAccounts)
|
||||||
if let context = context, let liveLocationManager = context.context.liveLocationManager {
|
|> deliverOn(Queue())).start(next: { infos in
|
||||||
let accountId = context.context.account.id
|
storeAccountsData(rootPath: rootPath, accounts: infos)
|
||||||
return liveLocationManager.isPolling
|
})
|
||||||
|> distinctUntilChanged
|
|
||||||
|> map { value -> AccountRecordId? in
|
sharedContext.presentGlobalController = { [weak self] c, a in
|
||||||
if value {
|
guard let strongSelf = self else {
|
||||||
return accountId
|
return
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
strongSelf.mainWindow.present(c, on: .root)
|
||||||
return .single(nil)
|
}
|
||||||
|
sharedContext.presentCrossfadeController = { [weak self] in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var exists = false
|
||||||
|
strongSelf.mainWindow.forEachViewController { controller in
|
||||||
|
if controller is ThemeSettingsCrossfadeController {
|
||||||
|
exists = true
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
strongSelf.mainWindow.present(ThemeSettingsCrossfadeController(), on: .root)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let notificationManager = SharedNotificationManager(episodeId: self.episodeId, application: application, clearNotificationsManager: clearNotificationsManager, inForeground: applicationBindings.applicationInForeground, accounts: sharedContext.activeAccounts |> map { primary, accounts, _ in accounts.map({ ($0.1, $0.1.id == primary?.id) }) }, pollLiveLocationOnce: { accountId in
|
||||||
|
let _ = (self.context.get()
|
||||||
|
|> filter {
|
||||||
|
return $0 != nil
|
||||||
|
}
|
||||||
|
|> take(1)
|
||||||
|
|> deliverOnMainQueue).start(next: { context in
|
||||||
|
if let context = context, context.context.account.id == accountId {
|
||||||
|
context.context.liveLocationManager?.pollOnce()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
setPresentationCall = { call in
|
||||||
|
notificationManager.setNotificationCall(call, strings: sharedContext.currentPresentationData.with({ $0 }).strings)
|
||||||
|
}
|
||||||
|
let liveLocationPolling = self.context.get()
|
||||||
|
|> mapToSignal { context -> Signal<AccountRecordId?, NoError> in
|
||||||
|
if let context = context, let liveLocationManager = context.context.liveLocationManager {
|
||||||
|
let accountId = context.context.account.id
|
||||||
|
return liveLocationManager.isPolling
|
||||||
|
|> distinctUntilChanged
|
||||||
|
|> map { value -> AccountRecordId? in
|
||||||
|
if value {
|
||||||
|
return accountId
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return .single(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let watchTasks = self.context.get()
|
||||||
|
|> mapToSignal { context -> Signal<AccountRecordId?, NoError> in
|
||||||
|
if let context = context, let watchManager = context.context.watchManager {
|
||||||
|
let accountId = context.context.account.id
|
||||||
|
let runningTasks: Signal<WatchRunningTasks?, NoError> = .single(nil)
|
||||||
|
|> then(watchManager.runningTasks)
|
||||||
|
return runningTasks
|
||||||
|
|> distinctUntilChanged
|
||||||
|
|> map { value -> AccountRecordId? in
|
||||||
|
if let value = value, value.running {
|
||||||
|
return accountId
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|> distinctUntilChanged
|
||||||
|
} else {
|
||||||
|
return .single(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let wakeupManager = SharedWakeupManager(beginBackgroundTask: { name, expiration in application.beginBackgroundTask(withName: name, expirationHandler: expiration) }, endBackgroundTask: { id in application.endBackgroundTask(id) }, backgroundTimeRemaining: { application.backgroundTimeRemaining }, activeAccounts: sharedContext.activeAccounts |> map { ($0.0, $0.1.map { ($0.0, $0.1) }) }, liveLocationPolling: liveLocationPolling, watchTasks: watchTasks, inForeground: applicationBindings.applicationInForeground, hasActiveAudioSession: self.hasActiveAudioSession.get(), notificationManager: notificationManager, mediaManager: sharedContext.mediaManager, callManager: sharedContext.callManager, accountUserInterfaceInUse: { id in
|
||||||
|
return sharedContext.accountUserInterfaceInUse(id)
|
||||||
|
})
|
||||||
|
let sharedApplicationContext = SharedApplicationContext(sharedContext: sharedContext, notificationManager: notificationManager, wakeupManager: wakeupManager)
|
||||||
|
sharedApplicationContext.sharedContext.mediaManager.overlayMediaManager.attachOverlayMediaController(sharedApplicationContext.overlayMediaController)
|
||||||
|
|
||||||
|
return accountManager.transaction { transaction -> (SharedApplicationContext, LoggingSettings) in
|
||||||
|
return (sharedApplicationContext, transaction.getSharedData(SharedDataKeys.loggingSettings) as? LoggingSettings ?? LoggingSettings.defaultSettings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let watchTasks = self.context.get()
|
self.sharedContextPromise.set(sharedContextSignal
|
||||||
|> mapToSignal { context -> Signal<AccountRecordId?, NoError> in
|
|
||||||
if let context = context, let watchManager = context.context.watchManager {
|
|
||||||
let accountId = context.context.account.id
|
|
||||||
let runningTasks: Signal<WatchRunningTasks?, NoError> = .single(nil)
|
|
||||||
|> then(watchManager.runningTasks)
|
|
||||||
return runningTasks
|
|
||||||
|> distinctUntilChanged
|
|
||||||
|> map { value -> AccountRecordId? in
|
|
||||||
if let value = value, value.running {
|
|
||||||
return accountId
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|> distinctUntilChanged
|
|
||||||
} else {
|
|
||||||
return .single(nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let wakeupManager = SharedWakeupManager(beginBackgroundTask: { name, expiration in application.beginBackgroundTask(withName: name, expirationHandler: expiration) }, endBackgroundTask: { id in application.endBackgroundTask(id) }, backgroundTimeRemaining: { application.backgroundTimeRemaining }, activeAccounts: sharedContext.activeAccounts |> map { ($0.0, $0.1.map { ($0.0, $0.1) }) }, liveLocationPolling: liveLocationPolling, watchTasks: watchTasks, inForeground: applicationBindings.applicationInForeground, hasActiveAudioSession: hasActiveAudioSession.get(), notificationManager: notificationManager, mediaManager: sharedContext.mediaManager, callManager: sharedContext.callManager, accountUserInterfaceInUse: { id in
|
|
||||||
return sharedContext.accountUserInterfaceInUse(id)
|
|
||||||
})
|
|
||||||
let sharedApplicationContext = SharedApplicationContext(sharedContext: sharedContext, notificationManager: notificationManager, wakeupManager: wakeupManager)
|
|
||||||
sharedApplicationContext.sharedContext.mediaManager.overlayMediaManager.attachOverlayMediaController(sharedApplicationContext.overlayMediaController)
|
|
||||||
self.sharedContextPromise.set(
|
|
||||||
accountManager.transaction { transaction -> (SharedApplicationContext, LoggingSettings) in
|
|
||||||
return (sharedApplicationContext, transaction.getSharedData(SharedDataKeys.loggingSettings) as? LoggingSettings ?? LoggingSettings.defaultSettings)
|
|
||||||
}
|
|
||||||
|> mapToSignal { sharedApplicationContext, loggingSettings -> Signal<SharedApplicationContext, NoError> in
|
|> mapToSignal { sharedApplicationContext, loggingSettings -> Signal<SharedApplicationContext, NoError> in
|
||||||
Logger.shared.logToFile = loggingSettings.logToFile
|
Logger.shared.logToFile = loggingSettings.logToFile
|
||||||
Logger.shared.logToConsole = loggingSettings.logToConsole
|
Logger.shared.logToConsole = loggingSettings.logToConsole
|
||||||
Logger.shared.redactSensitiveData = loggingSettings.redactSensitiveData
|
Logger.shared.redactSensitiveData = loggingSettings.redactSensitiveData
|
||||||
|
|
||||||
return importedLegacyAccount(basePath: appGroupUrl.path, accountManager: sharedApplicationContext.sharedContext.accountManager, present: { controller in
|
return importedLegacyAccount(basePath: appGroupUrl.path, accountManager: sharedApplicationContext.sharedContext.accountManager, encryptionKey: encryptionKey, present: { controller in
|
||||||
self.window?.rootViewController?.present(controller, animated: true, completion: nil)
|
self.window?.rootViewController?.present(controller, animated: true, completion: nil)
|
||||||
})
|
})
|
||||||
|> `catch` { _ -> Signal<ImportedLegacyAccountEvent, NoError> in
|
|> `catch` { _ -> Signal<ImportedLegacyAccountEvent, NoError> in
|
||||||
@@ -720,7 +745,7 @@ private final class SharedApplicationContext {
|
|||||||
case let .progress(type, value):
|
case let .progress(type, value):
|
||||||
Queue.mainQueue().async {
|
Queue.mainQueue().async {
|
||||||
if self.dataImportSplash == nil {
|
if self.dataImportSplash == nil {
|
||||||
self.dataImportSplash = LegacyDataImportSplash()
|
self.dataImportSplash = LegacyDataImportSplash(theme: nil, strings: nil)
|
||||||
self.dataImportSplash?.serviceAction = {
|
self.dataImportSplash?.serviceAction = {
|
||||||
self.debugPressed()
|
self.debugPressed()
|
||||||
}
|
}
|
||||||
@@ -793,7 +818,7 @@ private final class SharedApplicationContext {
|
|||||||
|> map { accountAndSettings -> AuthorizedApplicationContext? in
|
|> map { accountAndSettings -> AuthorizedApplicationContext? in
|
||||||
return accountAndSettings.flatMap { account, limitsConfiguration, callListSettings in
|
return accountAndSettings.flatMap { account, limitsConfiguration, callListSettings in
|
||||||
let context = AccountContext(sharedContext: sharedApplicationContext.sharedContext, account: account, limitsConfiguration: limitsConfiguration)
|
let context = AccountContext(sharedContext: sharedApplicationContext.sharedContext, account: account, limitsConfiguration: limitsConfiguration)
|
||||||
return AuthorizedApplicationContext(mainWindow: self.mainWindow, watchManagerArguments: watchManagerArgumentsPromise.get(), context: context, accountManager: sharedApplicationContext.sharedContext.accountManager, showCallsTab: callListSettings.showTab, reinitializedNotificationSettings: {
|
return AuthorizedApplicationContext(sharedApplicationContext: sharedApplicationContext, mainWindow: self.mainWindow, watchManagerArguments: watchManagerArgumentsPromise.get(), context: context, accountManager: sharedApplicationContext.sharedContext.accountManager, showCallsTab: callListSettings.showTab, reinitializedNotificationSettings: {
|
||||||
let _ = (self.context.get()
|
let _ = (self.context.get()
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> deliverOnMainQueue).start(next: { context in
|
|> deliverOnMainQueue).start(next: { context in
|
||||||
@@ -932,7 +957,7 @@ private final class SharedApplicationContext {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
self.mainWindow.topLevelOverlayControllers = [sharedApplicationContext.overlayMediaController, context.notificationController]
|
self.mainWindow.topLevelOverlayControllers = [context.sharedApplicationContext.overlayMediaController, context.notificationController]
|
||||||
var authorizeNotifications = true
|
var authorizeNotifications = true
|
||||||
if #available(iOS 10.0, *) {
|
if #available(iOS 10.0, *) {
|
||||||
authorizeNotifications = false
|
authorizeNotifications = false
|
||||||
@@ -979,7 +1004,10 @@ private final class SharedApplicationContext {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
self.watchCommunicationManagerPromise.set(watchCommunicationManager(context: self.context, allowBackgroundTimeExtension: { timeout in
|
self.watchCommunicationManagerPromise.set(watchCommunicationManager(context: self.context, allowBackgroundTimeExtension: { timeout in
|
||||||
wakeupManager.allowBackgroundTimeExtension(timeout: timeout)
|
let _ = (self.sharedContextPromise.get()
|
||||||
|
|> take(1)).start(next: { sharedContext in
|
||||||
|
sharedContext.wakeupManager.allowBackgroundTimeExtension(timeout: timeout)
|
||||||
|
})
|
||||||
}))
|
}))
|
||||||
let _ = self.watchCommunicationManagerPromise.get().start(next: { manager in
|
let _ = self.watchCommunicationManagerPromise.get().start(next: { manager in
|
||||||
if let manager = manager {
|
if let manager = manager {
|
||||||
@@ -1059,8 +1087,10 @@ private final class SharedApplicationContext {
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
let presentationData = sharedContext.currentPresentationData.with { $0 }
|
if let sharedContext = strongSelf.contextValue?.context.sharedContext {
|
||||||
strongSelf.mainWindow.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: alert.title, text: alert.message ?? "", actions: actions), on: .root)
|
let presentationData = sharedContext.currentPresentationData.with { $0 }
|
||||||
|
strongSelf.mainWindow.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: alert.title, text: alert.message ?? "", actions: actions), on: .root)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ private struct PasscodeState: Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class AuthorizedApplicationContext {
|
final class AuthorizedApplicationContext {
|
||||||
|
let sharedApplicationContext: SharedApplicationContext
|
||||||
let mainWindow: Window1
|
let mainWindow: Window1
|
||||||
let lockedCoveringView: LockedWindowCoveringView
|
let lockedCoveringView: LockedWindowCoveringView
|
||||||
|
|
||||||
@@ -99,7 +100,9 @@ final class AuthorizedApplicationContext {
|
|||||||
private var showCallsTabDisposable: Disposable?
|
private var showCallsTabDisposable: Disposable?
|
||||||
private var enablePostboxTransactionsDiposable: Disposable?
|
private var enablePostboxTransactionsDiposable: Disposable?
|
||||||
|
|
||||||
init(mainWindow: Window1, watchManagerArguments: Signal<WatchManagerArguments?, NoError>, context: AccountContext, accountManager: AccountManager, showCallsTab: Bool, reinitializedNotificationSettings: @escaping () -> Void) {
|
init(sharedApplicationContext: SharedApplicationContext, mainWindow: Window1, watchManagerArguments: Signal<WatchManagerArguments?, NoError>, context: AccountContext, accountManager: AccountManager, showCallsTab: Bool, reinitializedNotificationSettings: @escaping () -> Void) {
|
||||||
|
self.sharedApplicationContext = sharedApplicationContext
|
||||||
|
|
||||||
setupLegacyComponents(context: context)
|
setupLegacyComponents(context: context)
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
|
||||||
@@ -121,6 +124,9 @@ final class AuthorizedApplicationContext {
|
|||||||
if KeyShortcutsController.isAvailable {
|
if KeyShortcutsController.isAvailable {
|
||||||
let keyShortcutsController = KeyShortcutsController { [weak self] f in
|
let keyShortcutsController = KeyShortcutsController { [weak self] f in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
|
if strongSelf.isLocked {
|
||||||
|
return
|
||||||
|
}
|
||||||
if let tabController = strongSelf.rootController.rootTabController {
|
if let tabController = strongSelf.rootController.rootTabController {
|
||||||
let controller = tabController.controllers[tabController.selectedIndex]
|
let controller = tabController.controllers[tabController.selectedIndex]
|
||||||
if !f(controller) {
|
if !f(controller) {
|
||||||
@@ -695,10 +701,20 @@ final class AuthorizedApplicationContext {
|
|||||||
|
|
||||||
self.displayAlertsDisposable = (context.account.stateManager.displayAlerts
|
self.displayAlertsDisposable = (context.account.stateManager.displayAlerts
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] alerts in
|
|> deliverOnMainQueue).start(next: { [weak self] alerts in
|
||||||
if let strongSelf = self{
|
if let strongSelf = self {
|
||||||
for text in alerts {
|
for (text, isDropAuth) in alerts {
|
||||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
let controller = textAlertController(context: strongSelf.context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])
|
let actions: [TextAlertAction]
|
||||||
|
if isDropAuth {
|
||||||
|
actions = [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.LogoutOptions_LogOut, action: {
|
||||||
|
if let strongSelf = self {
|
||||||
|
let _ = logoutFromAccount(id: strongSelf.context.account.id, accountManager: strongSelf.context.sharedContext.accountManager).start()
|
||||||
|
}
|
||||||
|
})]
|
||||||
|
} else {
|
||||||
|
actions = [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]
|
||||||
|
}
|
||||||
|
let controller = textAlertController(context: strongSelf.context, title: nil, text: text, actions: actions)
|
||||||
(strongSelf.rootController.viewControllers.last as? ViewController)?.present(controller, in: .window(.root))
|
(strongSelf.rootController.viewControllers.last as? ViewController)?.present(controller, in: .window(.root))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,4 +13,6 @@
|
|||||||
@property (nonatomic, readonly) int64_t appStoreId;
|
@property (nonatomic, readonly) int64_t appStoreId;
|
||||||
@property (nonatomic, strong, readonly) NSString * _Nonnull appSpecificUrlScheme;
|
@property (nonatomic, strong, readonly) NSString * _Nonnull appSpecificUrlScheme;
|
||||||
|
|
||||||
|
+ (NSData * _Nonnull)encryptionKey:(NSString * _Nonnull)rootPath;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -382,4 +382,17 @@ static MTPKCS * _Nullable checkSignature(const char *filename) {
|
|||||||
return @(APP_SPECIFIC_URL_SCHEME);
|
return @(APP_SPECIFIC_URL_SCHEME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (NSData * _Nonnull)encryptionKey:(NSString * _Nonnull)rootPath {
|
||||||
|
NSString *filePath = [rootPath stringByAppendingPathComponent:@".tempkey"];
|
||||||
|
NSData *data = [NSData dataWithContentsOfFile:filePath];
|
||||||
|
if (data != nil) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
NSMutableData *randomData = [[NSMutableData alloc] initWithLength:32];
|
||||||
|
int result = SecRandomCopyBytes(kSecRandomDefault, randomData.length, [randomData mutableBytes]);
|
||||||
|
assert(result == 0);
|
||||||
|
[randomData writeToFile:filePath atomically:false];
|
||||||
|
return randomData;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>5.5</string>
|
<string>5.5.1</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ enum ImportedLegacyAccountEvent {
|
|||||||
case result(AccountRecordId?)
|
case result(AccountRecordId?)
|
||||||
}
|
}
|
||||||
|
|
||||||
func importedLegacyAccount(basePath: String, accountManager: AccountManager, present: @escaping (UIViewController) -> Void) -> Signal<ImportedLegacyAccountEvent, AccountImportError> {
|
func importedLegacyAccount(basePath: String, accountManager: AccountManager, encryptionKey: Data, present: @escaping (UIViewController) -> Void) -> Signal<ImportedLegacyAccountEvent, AccountImportError> {
|
||||||
let queue = Queue()
|
let queue = Queue()
|
||||||
return deferred { () -> Signal<ImportedLegacyAccountEvent, AccountImportError> in
|
return deferred { () -> Signal<ImportedLegacyAccountEvent, AccountImportError> in
|
||||||
let documentsPath = basePath + "/Documents"
|
let documentsPath = basePath + "/Documents"
|
||||||
@@ -218,7 +218,7 @@ func importedLegacyAccount(basePath: String, accountManager: AccountManager, pre
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return temporaryAccount(manager: accountManager, rootPath: rootPathForBasePath(basePath))
|
return temporaryAccount(manager: accountManager, rootPath: rootPathForBasePath(basePath), encryptionKey: encryptionKey)
|
||||||
|> introduceError(AccountImportError.self)
|
|> introduceError(AccountImportError.self)
|
||||||
|> mapToSignal { account -> Signal<ImportedLegacyAccountEvent, AccountImportError> in
|
|> mapToSignal { account -> Signal<ImportedLegacyAccountEvent, AccountImportError> in
|
||||||
let actions = importedAccountData(basePath: basePath, documentsPath: documentsPath, accountManager: accountManager, account: account, database: database)
|
let actions = importedAccountData(basePath: basePath, documentsPath: documentsPath, accountManager: accountManager, account: account, database: database)
|
||||||
|
|||||||
@@ -4,22 +4,25 @@ import AsyncDisplayKit
|
|||||||
import TelegramUI
|
import TelegramUI
|
||||||
|
|
||||||
final class LegacyDataImportSplash: WindowCoveringView {
|
final class LegacyDataImportSplash: WindowCoveringView {
|
||||||
|
private let theme: PresentationTheme?
|
||||||
|
private let strings: PresentationStrings?
|
||||||
|
|
||||||
var progress: (AccountImportProgressType, Float) = (.generic, 0.0) {
|
var progress: (AccountImportProgressType, Float) = (.generic, 0.0) {
|
||||||
didSet {
|
didSet {
|
||||||
if self.progress.0 != oldValue.0 {
|
if self.progress.0 != oldValue.0 {
|
||||||
if let size = self.validSize {
|
if let size = self.validSize {
|
||||||
switch self.progress.0 {
|
switch self.progress.0 {
|
||||||
case .generic:
|
case .generic:
|
||||||
self.textNode.attributedText = NSAttributedString(string: "Optimizing", font: Font.regular(17.0), textColor: .black)
|
self.textNode.attributedText = NSAttributedString(string: self.strings?.DataUpgrade_Running ?? "Optimizing...", font: Font.regular(17.0), textColor: self.theme?.list.itemPrimaryTextColor ?? .black)
|
||||||
case .media:
|
case .media:
|
||||||
self.textNode.attributedText = NSAttributedString(string: "Optimizing cache", font: Font.regular(17.0), textColor: .black)
|
self.textNode.attributedText = NSAttributedString(string: "Optimizing cache", font: Font.regular(17.0), textColor: self.theme?.list.itemPrimaryTextColor ?? .black)
|
||||||
case .messages:
|
case .messages:
|
||||||
self.textNode.attributedText = NSAttributedString(string: "Optimizing database", font: Font.regular(17.0), textColor: .black)
|
self.textNode.attributedText = NSAttributedString(string: "Optimizing database", font: Font.regular(17.0), textColor: self.theme?.list.itemPrimaryTextColor ?? .black)
|
||||||
}
|
}
|
||||||
self.updateLayout(size)
|
self.updateLayout(size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.progressNode.transitionToState(.progress(color: UIColor(rgb: 0x007ee5), lineWidth: 2.0, value: CGFloat(max(0.025, self.progress.1)), cancelEnabled: false), animated: false, completion: {})
|
self.progressNode.transitionToState(.progress(color: self.theme?.list.itemAccentColor ?? UIColor(rgb: 0x007ee5), lineWidth: 2.0, value: CGFloat(max(0.025, self.progress.1)), cancelEnabled: false), animated: false, completion: {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,12 +33,17 @@ final class LegacyDataImportSplash: WindowCoveringView {
|
|||||||
|
|
||||||
private var validSize: CGSize?
|
private var validSize: CGSize?
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
init(theme: PresentationTheme?, strings: PresentationStrings?) {
|
||||||
self.progressNode = RadialStatusNode(backgroundNodeColor: UIColor.white)
|
self.theme = theme
|
||||||
self.textNode = ImmediateTextNode()
|
self.strings = strings
|
||||||
self.textNode.attributedText = NSAttributedString(string: "Optimizing", font: Font.regular(17.0), textColor: .black)
|
|
||||||
|
|
||||||
super.init(frame: frame)
|
self.progressNode = RadialStatusNode(backgroundNodeColor: theme?.list.plainBackgroundColor ?? .white)
|
||||||
|
self.textNode = ImmediateTextNode()
|
||||||
|
self.textNode.attributedText = NSAttributedString(string: self.strings?.DataUpgrade_Running ?? "Optimizing...", font: Font.regular(17.0), textColor: self.theme?.list.itemPrimaryTextColor ?? .black)
|
||||||
|
|
||||||
|
super.init(frame: CGRect())
|
||||||
|
|
||||||
|
self.backgroundColor = self.theme?.list.plainBackgroundColor ?? .white
|
||||||
|
|
||||||
self.addSubnode(self.progressNode)
|
self.addSubnode(self.progressNode)
|
||||||
self.progressNode.isUserInteractionEnabled = false
|
self.progressNode.isUserInteractionEnabled = false
|
||||||
|
|||||||
@@ -198,6 +198,7 @@ final class SharedNotificationManager {
|
|||||||
let aps = payload["aps"] as? [AnyHashable: Any]
|
let aps = payload["aps"] as? [AnyHashable: Any]
|
||||||
|
|
||||||
var readMessageId: MessageId?
|
var readMessageId: MessageId?
|
||||||
|
var removedMessageId: MessageId?
|
||||||
var isCall = false
|
var isCall = false
|
||||||
var isAnnouncement = false
|
var isAnnouncement = false
|
||||||
var isLocationPolling = false
|
var isLocationPolling = false
|
||||||
|
|||||||
@@ -3926,8 +3926,9 @@ Unused sets are archived when you add more.";
|
|||||||
"ChatList.DeleteSavedMessagesConfirmation" = "Are you sure you want to delete\nSaved Messages?";
|
"ChatList.DeleteSavedMessagesConfirmation" = "Are you sure you want to delete\nSaved Messages?";
|
||||||
|
|
||||||
"Undo.Undo" = "Undo";
|
"Undo.Undo" = "Undo";
|
||||||
"Undo.MessagesDeleted" = "Messages deleted";
|
|
||||||
"Undo.ChatDeleted" = "Chat deleted";
|
"Undo.ChatDeleted" = "Chat deleted";
|
||||||
|
"Undo.ChatCleared" = "Chat cleared";
|
||||||
|
"Undo.ChatClearedForBothSides" = "Chat cleared for both sides";
|
||||||
"Undo.SecretChatDeleted" = "Secret Chat deleted";
|
"Undo.SecretChatDeleted" = "Secret Chat deleted";
|
||||||
"Undo.LeftChannel" = "Left channel";
|
"Undo.LeftChannel" = "Left channel";
|
||||||
"Undo.LeftGroup" = "Left group";
|
"Undo.LeftGroup" = "Left group";
|
||||||
@@ -4195,3 +4196,12 @@ Unused sets are archived when you add more.";
|
|||||||
"ChatList.DeleteForEveryone" = "Delete for me and %@";
|
"ChatList.DeleteForEveryone" = "Delete for me and %@";
|
||||||
|
|
||||||
"ChatList.ClearChatConfirmation" = "Are you sure you want to delete all\nmessages in the chat with %@?";
|
"ChatList.ClearChatConfirmation" = "Are you sure you want to delete all\nmessages in the chat with %@?";
|
||||||
|
|
||||||
|
"Settings.CheckPhoneNumberTitle" = "Is %@ still your number?";
|
||||||
|
"Settings.CheckPhoneNumberText" = "Keep your number up to date to ensure you can always log in to Telegram. [Learn more]()";
|
||||||
|
"Settings.KeepPhoneNumber" = "Keep %@";
|
||||||
|
"Settings.ChangePhoneNumber" = "Change Number";
|
||||||
|
|
||||||
|
"Undo.ChatDeletedForBothSides" = "Chat deleted for both sides";
|
||||||
|
|
||||||
|
"DataUpgrade.Running" = "Optimizing...";
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>5.5</string>
|
<string>5.5.1</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>${BUILD_NUMBER}</string>
|
<string>${BUILD_NUMBER}</string>
|
||||||
<key>UISupportedInterfaceOrientations</key>
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>XPC!</string>
|
<string>XPC!</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>5.5</string>
|
<string>5.5.1</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>${BUILD_NUMBER}</string>
|
<string>${BUILD_NUMBER}</string>
|
||||||
<key>NSExtension</key>
|
<key>NSExtension</key>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>XPC!</string>
|
<string>XPC!</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>5.5</string>
|
<string>5.5.1</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>${BUILD_NUMBER}</string>
|
<string>${BUILD_NUMBER}</string>
|
||||||
<key>NSExtension</key>
|
<key>NSExtension</key>
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ class TodayViewController: UIViewController, NCWidgetProviding {
|
|||||||
let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown"
|
let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown"
|
||||||
initializeAccountManagement()
|
initializeAccountManagement()
|
||||||
let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata")
|
let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata")
|
||||||
account = currentAccount(allocateIfNotExists: false, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0, appData: BuildConfig.shared().bundleData), supplementary: true, manager: accountManager, rootPath: rootPath, auxiliaryMethods: auxiliaryMethods)
|
account = currentAccount(allocateIfNotExists: false, networkArguments: NetworkInitializationArguments(apiId: apiId, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0, appData: BuildConfig.shared().bundleData), supplementary: true, manager: accountManager, rootPath: rootPath, auxiliaryMethods: auxiliaryMethods, encryptionKey: BuildConfig.encryptionKey(rootPath))
|
||||||
|> mapToSignal { account -> Signal<Account, NoError> in
|
|> mapToSignal { account -> Signal<Account, NoError> in
|
||||||
if let account = account {
|
if let account = account {
|
||||||
switch account {
|
switch account {
|
||||||
|
|||||||
2
buildbox/.gitignore
vendored
Normal file
2
buildbox/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
transient-data
|
||||||
|
|
||||||
91
buildbox/build-telegram.sh
Normal file
91
buildbox/build-telegram.sh
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BUILD_TELEGRAM_VERSION="1"
|
||||||
|
|
||||||
|
if [ `which cleanup-telegram-build-vms.sh` ]; then
|
||||||
|
cleanup-telegram-build-vms.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
BUILDBOX_DIR="buildbox"
|
||||||
|
|
||||||
|
mkdir -p "$BUILDBOX_DIR/transient-data"
|
||||||
|
|
||||||
|
BUILD_CONFIGURATION="$1"
|
||||||
|
|
||||||
|
if [ "$BUILD_CONFIGURATION" == "hockeyapp" ]; then
|
||||||
|
CODESIGNING_SUBPATH="transient-data/codesigning"
|
||||||
|
elif [ "$BUILD_CONFIGURATION" == "appstore" ]; then
|
||||||
|
CODESIGNING_SUBPATH="transient-data/codesigning"
|
||||||
|
elif [ "$BUILD_CONFIGURATION" == "verify" ]; then
|
||||||
|
CODESIGNING_SUBPATH="fake-codesigning"
|
||||||
|
else
|
||||||
|
echo "Unknown configuration $1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
BASE_DIR=$(pwd)
|
||||||
|
|
||||||
|
if [ "$BUILD_CONFIGURATION" == "hockeyapp" ] || [ "$BUILD_CONFIGURATION" == "appstore" ]; then
|
||||||
|
if [ ! `which setup-telegram-build.sh` ]; then
|
||||||
|
echo "setup-telegram-build.sh not found in PATH $PATH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
source `which setup-telegram-build.sh`
|
||||||
|
setup_telegram_build "$BUILD_CONFIGURATION" "$BASE_DIR/$BUILDBOX_DIR/transient-data"
|
||||||
|
if [ "$SETUP_TELEGRAM_BUILD_VERSION" != "$BUILD_TELEGRAM_VERSION" ]; then
|
||||||
|
echo "setup-telegram-build.sh script version doesn't match"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ "$BUILD_CONFIGURATION" == "appstore" ]; then
|
||||||
|
if [ -z "$TELEGRAM_BUILD_APPSTORE_PASSWORD" ]; then
|
||||||
|
echo "TELEGRAM_BUILD_APPSTORE_PASSWORD is not set"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "$BUILDBOX_DIR/$CODESIGNING_SUBPATH" ]; then
|
||||||
|
echo "$BUILDBOX_DIR/$CODESIGNING_SUBPATH does not exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SOURCE_DIR=$(basename "$BASE_DIR")
|
||||||
|
cd ..
|
||||||
|
rm -f "$SOURCE_DIR/$BUILDBOX_DIR/transient-data/source.tar"
|
||||||
|
tar cf "$SOURCE_DIR/$BUILDBOX_DIR/transient-data/source.tar" --exclude "$SOURCE_DIR/$BUILDBOX_DIR" "$SOURCE_DIR"
|
||||||
|
cd "$BASE_DIR"
|
||||||
|
|
||||||
|
VM_BASE_NAME="macos10_14_3_Xcode10_1"
|
||||||
|
|
||||||
|
SNAPSHOT_ID=$(prlctl snapshot-list "$VM_BASE_NAME" | grep -Eo '\{(\d|[a-f]|-)*\}' | tr '\n' '\0')
|
||||||
|
|
||||||
|
if [ -z "$SNAPSHOT_ID" ]; then
|
||||||
|
echo "$VM_BASE_NAME is required to have one snapshot"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PROCESS_ID="$$"
|
||||||
|
VM_NAME="$VM_BASE_NAME-$(openssl rand -hex 10)-build-telegram-$PROCESS_ID"
|
||||||
|
|
||||||
|
prlctl clone "$VM_BASE_NAME" --name "$VM_NAME"
|
||||||
|
prlctl snapshot-switch "$VM_NAME" -i "$SNAPSHOT_ID"
|
||||||
|
|
||||||
|
VM_IP=$(prlctl exec "$VM_NAME" "ifconfig | grep inet | grep broadcast | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' | head -1 | tr '\n' '\0'")
|
||||||
|
|
||||||
|
scp -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -pr "$BUILDBOX_DIR/$CODESIGNING_SUBPATH" telegram@"$VM_IP":codesigning_data
|
||||||
|
|
||||||
|
if [ "$BUILD_CONFIGURATION" == "verify" ]; then
|
||||||
|
scp -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -pr "$BUILDBOX_DIR/fake-shared" telegram@"$VM_IP":telegram-ios-shared
|
||||||
|
else
|
||||||
|
scp -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -pr "$BUILDBOX_DIR/transient-data/telegram-ios-shared" telegram@"$VM_IP":telegram-ios-shared
|
||||||
|
fi
|
||||||
|
scp -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -pr "$BUILDBOX_DIR/guest-build-telegram.sh" "$BUILDBOX_DIR/transient-data/source.tar" telegram@"$VM_IP":
|
||||||
|
|
||||||
|
ssh -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null telegram@"$VM_IP" -o ServerAliveInterval=60 -t "export TELEGRAM_BUILD_APPSTORE_PASSWORD=$TELEGRAM_BUILD_APPSTORE_PASSWORD; bash -l guest-build-telegram.sh $BUILD_CONFIGURATION"
|
||||||
|
|
||||||
|
scp -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -pr telegram@"$VM_IP":telegram-ios/Telegram-iOS-AppStoreLLC.ipa ./
|
||||||
|
|
||||||
|
prlctl stop "$VM_NAME" --kill
|
||||||
|
prlctl delete "$VM_NAME"
|
||||||
BIN
buildbox/fake-codesigning/certs/SelfSigned.p12
Normal file
BIN
buildbox/fake-codesigning/certs/SelfSigned.p12
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
8
buildbox/fake-shared/Config/AppStoreLLC/Config.xcconfig
Normal file
8
buildbox/fake-shared/Config/AppStoreLLC/Config.xcconfig
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
APP_NAME=Telegram
|
||||||
|
APP_BUNDLE_ID=ph.telegra.Telegraph
|
||||||
|
APP_SPECIFIC_URL_SCHEME=tgapp
|
||||||
|
|
||||||
|
GLOBAL_CONSTANTS = APP_CONFIG_IS_INTERNAL_BUILD=false APP_CONFIG_IS_APPSTORE_BUILD=true APP_CONFIG_APPSTORE_ID=686449807 APP_SPECIFIC_URL_SCHEME="\"$(APP_SPECIFIC_URL_SCHEME)\""
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) $(GLOBAL_CONSTANTS)
|
||||||
|
|
||||||
|
#include "Data.xcconfig"
|
||||||
1
buildbox/fake-shared/Config/AppStoreLLC/Data.xcconfig
Normal file
1
buildbox/fake-shared/Config/AppStoreLLC/Data.xcconfig
Normal file
@@ -0,0 +1 @@
|
|||||||
|
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) APP_CONFIG_DATA="\"\""
|
||||||
0
buildbox/fake-shared/fastlane/Fastfile
Normal file
0
buildbox/fake-shared/fastlane/Fastfile
Normal file
52
buildbox/guest-build-telegram.sh
Normal file
52
buildbox/guest-build-telegram.sh
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
if [ "$1" == "hockeyapp" ]; then
|
||||||
|
FASTLANE_BUILD_CONFIGURATION="internalhockeyapp"
|
||||||
|
elif [ "$1" == "appstore" ]; then
|
||||||
|
FASTLANE_BUILD_CONFIGURATION="testflight_llc"
|
||||||
|
if [ -z "$TELEGRAM_BUILD_APPSTORE_PASSWORD" ]; then
|
||||||
|
echo "TELEGRAM_BUILD_APPSTORE_PASSWORD is not set"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
FASTLANE_PASSWORD="$TELEGRAM_BUILD_APPSTORE_PASSWORD"
|
||||||
|
elif [ "$1" == "verify" ]; then
|
||||||
|
FASTLANE_BUILD_CONFIGURATION="build_for_appstore"
|
||||||
|
else
|
||||||
|
echo "Unknown configuration $1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
MY_KEYCHAIN="temp.keychain"
|
||||||
|
MY_KEYCHAIN_PASSWORD="secret"
|
||||||
|
|
||||||
|
security create-keychain -p "$MY_KEYCHAIN_PASSWORD" "$MY_KEYCHAIN"
|
||||||
|
security list-keychains -d user -s "$MY_KEYCHAIN" $(security list-keychains -d user | sed s/\"//g)
|
||||||
|
security set-keychain-settings "$MY_KEYCHAIN"
|
||||||
|
security unlock-keychain -p "$MY_KEYCHAIN_PASSWORD" "$MY_KEYCHAIN"
|
||||||
|
|
||||||
|
CERTS_PATH="codesigning_data/certs"
|
||||||
|
for f in $(ls "$CERTS_PATH"); do
|
||||||
|
fastlane run import_certificate "certificate_path:$CERTS_PATH/$f" keychain_name:"$MY_KEYCHAIN" keychain_password:"$MY_KEYCHAIN_PASSWORD" log_output:true
|
||||||
|
done
|
||||||
|
|
||||||
|
mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
|
||||||
|
|
||||||
|
PROFILES_PATH="codesigning_data/profiles"
|
||||||
|
for f in $(ls "$PROFILES_PATH"); do
|
||||||
|
PROFILE_PATH="$PROFILES_PATH/$f"
|
||||||
|
uuid=`grep UUID -A1 -a "$PROFILE_PATH" | grep -io "[-A-F0-9]\{36\}"`
|
||||||
|
cp "$PROFILE_PATH" "$HOME/Library/MobileDevice/Provisioning Profiles/$uuid.mobileprovision"
|
||||||
|
done
|
||||||
|
|
||||||
|
SOURCE_PATH="telegram-ios"
|
||||||
|
|
||||||
|
if [ -d "$SOURCE_PATH" ]; then
|
||||||
|
echo "$SOURCE_PATH must not exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Unpacking files..."
|
||||||
|
tar -xf "source.tar"
|
||||||
|
|
||||||
|
cd "$SOURCE_PATH"
|
||||||
|
FASTLANE_PASSWORD="$FASTLANE_PASSWORD" fastlane "$FASTLANE_BUILD_CONFIGURATION"
|
||||||
@@ -13,6 +13,7 @@ app_identifier_llc = [
|
|||||||
base_app_identifier_llc + ".watchkitapp.watchkitextension",
|
base_app_identifier_llc + ".watchkitapp.watchkitextension",
|
||||||
base_app_identifier_llc + ".NotificationService"
|
base_app_identifier_llc + ".NotificationService"
|
||||||
]
|
]
|
||||||
|
signing_identity_llc = "iPhone Distribution: Digital Fortress LLC (C67CF9S4VU)"
|
||||||
|
|
||||||
lane :do_build_app do |options|
|
lane :do_build_app do |options|
|
||||||
gym(
|
gym(
|
||||||
@@ -31,7 +32,8 @@ lane :do_build_app do |options|
|
|||||||
iCloudContainerEnvironment: "Production",
|
iCloudContainerEnvironment: "Production",
|
||||||
provisioningProfiles: options[:provisioningProfiles],
|
provisioningProfiles: options[:provisioningProfiles],
|
||||||
stripSwiftSymbols: true,
|
stripSwiftSymbols: true,
|
||||||
uploadBitcode: false
|
uploadBitcode: false,
|
||||||
|
signingCertificate: options[:signingCertificate]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
@@ -47,6 +49,7 @@ lane :build_for_appstore do |options|
|
|||||||
export_method: "app-store",
|
export_method: "app-store",
|
||||||
build_number: commit_count_string,
|
build_number: commit_count_string,
|
||||||
commit_id: commit[:commit_hash],
|
commit_id: commit[:commit_hash],
|
||||||
|
signingCertificate: signing_identity_llc,
|
||||||
provisioningProfiles: {
|
provisioningProfiles: {
|
||||||
base_app_identifier_llc => "match AppStore " + base_app_identifier_llc,
|
base_app_identifier_llc => "match AppStore " + base_app_identifier_llc,
|
||||||
base_app_identifier_llc + ".Share" => "match AppStore " + base_app_identifier_llc + ".Share",
|
base_app_identifier_llc + ".Share" => "match AppStore " + base_app_identifier_llc + ".Share",
|
||||||
|
|||||||
Submodule submodules/Display updated: 61d43c3c4b...7d0164259f
Submodule submodules/LegacyComponents updated: 0d44c9e101...443e039839
Submodule submodules/Postbox updated: 3d0b885f6a...434eeb4df2
Submodule submodules/TelegramCore updated: b3b73b2fde...414fc5cd9f
Submodule submodules/TelegramUI updated: 53b3408cb7...89715366c8
Submodule submodules/ffmpeg updated: 4ea8057cf2...0495e4606b
Reference in New Issue
Block a user