Merge branch 'master' into holes

This commit is contained in:
Peter
2019-03-30 00:07:15 +04:00
43 changed files with 394 additions and 159 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 {

View File

@@ -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,14 +573,18 @@ 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
}
let sharedContextSignal = accountManagerSignal
|> deliverOnMainQueue
|> mapToSignal { accountManager -> Signal<(SharedApplicationContext, LoggingSettings), NoError> in
var initialPresentationDataAndSettings: InitialPresentationDataAndSettings? var initialPresentationDataAndSettings: InitialPresentationDataAndSettings?
let semaphore = DispatchSemaphore(value: 0) let semaphore = DispatchSemaphore(value: 0)
let _ = currentPresentationDataAndSettings(accountManager: accountManager).start(next: { value in let _ = currentPresentationDataAndSettings(accountManager: accountManager).start(next: { value in
@@ -587,14 +593,31 @@ private final class SharedApplicationContext {
}) })
semaphore.wait() semaphore.wait()
if let initialPresentationDataAndSettings = initialPresentationDataAndSettings {
self.window?.backgroundColor = initialPresentationDataAndSettings.presentationData.theme.chatList.backgroundColor
}
let legacyBasePath = appGroupUrl.path let legacyBasePath = appGroupUrl.path
let legacyCache = LegacyCache(path: legacyBasePath + "/Caches") let legacyCache = LegacyCache(path: legacyBasePath + "/Caches")
var setPresentationCall: ((PresentationCall?) -> Void)? 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 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
setPresentationCall?(call) setPresentationCall?(call)
}, navigateToChat: { accountId, peerId, messageId in }, navigateToChat: { accountId, peerId, messageId in
self.openChatWhenReady(accountId: accountId, peerId: peerId, messageId: messageId) self.openChatWhenReady(accountId: accountId, peerId: peerId, messageId: messageId)
}, displayUpgradeProgress: { progress in
if let progress = progress {
if self.dataImportSplash == nil {
self.dataImportSplash = LegacyDataImportSplash(theme: initialPresentationDataAndSettings?.presentationData.theme, strings: initialPresentationDataAndSettings?.presentationData.strings)
self.mainWindow.coveringView = self.dataImportSplash
}
self.dataImportSplash?.progress = (.generic, progress)
} else if let dataImportSplash = self.dataImportSplash {
self.dataImportSplash = nil
if self.mainWindow.coveringView === dataImportSplash {
self.mainWindow.coveringView = nil
}
}
}) })
let rawAccounts = sharedContext.activeAccounts let rawAccounts = sharedContext.activeAccounts
@@ -681,21 +704,23 @@ private final class SharedApplicationContext {
return .single(nil) 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 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) return sharedContext.accountUserInterfaceInUse(id)
}) })
let sharedApplicationContext = SharedApplicationContext(sharedContext: sharedContext, notificationManager: notificationManager, wakeupManager: wakeupManager) let sharedApplicationContext = SharedApplicationContext(sharedContext: sharedContext, notificationManager: notificationManager, wakeupManager: wakeupManager)
sharedApplicationContext.sharedContext.mediaManager.overlayMediaManager.attachOverlayMediaController(sharedApplicationContext.overlayMediaController) sharedApplicationContext.sharedContext.mediaManager.overlayMediaManager.attachOverlayMediaController(sharedApplicationContext.overlayMediaController)
self.sharedContextPromise.set(
accountManager.transaction { transaction -> (SharedApplicationContext, LoggingSettings) in return accountManager.transaction { transaction -> (SharedApplicationContext, LoggingSettings) in
return (sharedApplicationContext, transaction.getSharedData(SharedDataKeys.loggingSettings) as? LoggingSettings ?? LoggingSettings.defaultSettings) return (sharedApplicationContext, transaction.getSharedData(SharedDataKeys.loggingSettings) as? LoggingSettings ?? LoggingSettings.defaultSettings)
} }
}
self.sharedContextPromise.set(sharedContextSignal
|> 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,9 +1087,11 @@ private final class SharedApplicationContext {
} }
})) }))
} }
if let sharedContext = strongSelf.contextValue?.context.sharedContext {
let presentationData = sharedContext.currentPresentationData.with { $0 } 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) strongSelf.mainWindow.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: alert.title, text: alert.message ?? "", actions: actions), on: .root)
} }
}
}) })
BITHockeyBaseManager.setPresentView({ [weak self] controller in BITHockeyBaseManager.setPresentView({ [weak self] controller in

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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
View File

@@ -0,0 +1,2 @@
transient-data

View 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"

Binary file not shown.

View 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"

View File

@@ -0,0 +1 @@
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) APP_CONFIG_DATA="\"\""

View File

View 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"

View File

@@ -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",