mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-16 03:09:56 +00:00
Added support for derived localizations
Added support for confirming two-step verification email via code
This commit is contained in:
parent
532285b062
commit
eecd183a28
@ -113,6 +113,8 @@
|
||||
D017495E1E118F790057C89A /* AccountStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D017495D1E118F790057C89A /* AccountStateManager.swift */; };
|
||||
D01749601E118FC30057C89A /* AccountIntermediateState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D017495F1E118FC30057C89A /* AccountIntermediateState.swift */; };
|
||||
D0177B7B1DF8A16C00A5083A /* SecretChatState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0177B7A1DF8A16C00A5083A /* SecretChatState.swift */; };
|
||||
D01843A82190C28100278AFF /* ConfirmTwoStepRecoveryEmail.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01843A72190C28100278AFF /* ConfirmTwoStepRecoveryEmail.swift */; };
|
||||
D01843A92190C28100278AFF /* ConfirmTwoStepRecoveryEmail.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01843A72190C28100278AFF /* ConfirmTwoStepRecoveryEmail.swift */; };
|
||||
D018D3371E648ACF00C5E089 /* ChannelCreation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D018D3361E648ACF00C5E089 /* ChannelCreation.swift */; };
|
||||
D018D3381E648ACF00C5E089 /* ChannelCreation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D018D3361E648ACF00C5E089 /* ChannelCreation.swift */; };
|
||||
D018EE002044939F00CBB130 /* SecretApiLayer73.swift in Sources */ = {isa = PBXBuildFile; fileRef = D018EDFF2044939F00CBB130 /* SecretApiLayer73.swift */; };
|
||||
@ -807,6 +809,7 @@
|
||||
D017495D1E118F790057C89A /* AccountStateManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountStateManager.swift; sourceTree = "<group>"; };
|
||||
D017495F1E118FC30057C89A /* AccountIntermediateState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountIntermediateState.swift; sourceTree = "<group>"; };
|
||||
D0177B7A1DF8A16C00A5083A /* SecretChatState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretChatState.swift; sourceTree = "<group>"; };
|
||||
D01843A72190C28100278AFF /* ConfirmTwoStepRecoveryEmail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmTwoStepRecoveryEmail.swift; sourceTree = "<group>"; };
|
||||
D018D3361E648ACF00C5E089 /* ChannelCreation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChannelCreation.swift; sourceTree = "<group>"; };
|
||||
D018EDFF2044939F00CBB130 /* SecretApiLayer73.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretApiLayer73.swift; sourceTree = "<group>"; };
|
||||
D018EE0120458E1E00CBB130 /* SecretChatLayerNegotiation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecretChatLayerNegotiation.swift; sourceTree = "<group>"; };
|
||||
@ -1552,6 +1555,7 @@
|
||||
D0B1671C1F9EA2C300976B40 /* ChatHistoryPreloadManager.swift */,
|
||||
D06ECFC720B810D300C576C2 /* TermsOfService.swift */,
|
||||
D051DB16215ECC4D00F30F92 /* AppChangelog.swift */,
|
||||
D01843A72190C28100278AFF /* ConfirmTwoStepRecoveryEmail.swift */,
|
||||
);
|
||||
name = Account;
|
||||
sourceTree = "<group>";
|
||||
@ -2209,6 +2213,7 @@
|
||||
D0ADF911212B00DD00310BBC /* SecureIdConfiguration.swift in Sources */,
|
||||
D0448CA51E29215A005A61A7 /* MediaResourceApiUtils.swift in Sources */,
|
||||
D0C26D661FE022DB004ABF18 /* SynchronizeGroupedPeersOperation.swift in Sources */,
|
||||
D01843A82190C28100278AFF /* ConfirmTwoStepRecoveryEmail.swift in Sources */,
|
||||
D03C53771DAFF20F004C17B3 /* MultipartUpload.swift in Sources */,
|
||||
D00C7CE01E3785710080C3D5 /* MarkMessageContentAsConsumedInteractively.swift in Sources */,
|
||||
C2E0646D1ECF171D00387BB8 /* TelegramMediaWebDocument.swift in Sources */,
|
||||
@ -2790,6 +2795,7 @@
|
||||
D0B844301DAB91E0005F29E1 /* NBNumberFormat.m in Sources */,
|
||||
D001F3F71E128A1C007A8C60 /* ApplyUpdateMessage.swift in Sources */,
|
||||
D0B418971D7E0580004562A4 /* TelegramMediaImage.swift in Sources */,
|
||||
D01843A92190C28100278AFF /* ConfirmTwoStepRecoveryEmail.swift in Sources */,
|
||||
D041E3F91E535A88008C24B4 /* RemovePeerMember.swift in Sources */,
|
||||
D049EAF61E44DF3300A2CD3A /* AccountState.swift in Sources */,
|
||||
D0467D1620D7F2C90055C28F /* ManagedSynchronizeMarkAllUnseenPersonalMessagesOperations.swift in Sources */,
|
||||
|
||||
@ -153,7 +153,7 @@ public class UnauthorizedAccount {
|
||||
return self.postbox.transaction { transaction -> (LocalizationSettings?, ProxySettings?, NetworkSettings?) in
|
||||
return (transaction.getPreferencesEntry(key: PreferencesKeys.localizationSettings) as? LocalizationSettings, transaction.getPreferencesEntry(key: PreferencesKeys.proxySettings) as? ProxySettings, transaction.getPreferencesEntry(key: PreferencesKeys.networkSettings) as? NetworkSettings)
|
||||
} |> mapToSignal { (localizationSettings, proxySettings, networkSettings) -> Signal<UnauthorizedAccount, NoError> in
|
||||
return initializedNetwork(arguments: self.networkArguments, supplementary: false, datacenterId: Int(masterDatacenterId), keychain: keychain, basePath: self.basePath, testingEnvironment: self.testingEnvironment, languageCode: localizationSettings?.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil)
|
||||
return initializedNetwork(arguments: self.networkArguments, supplementary: false, datacenterId: Int(masterDatacenterId), keychain: keychain, basePath: self.basePath, testingEnvironment: self.testingEnvironment, languageCode: localizationSettings?.primaryComponent.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil)
|
||||
|> map { network in
|
||||
let updated = UnauthorizedAccount(networkArguments: self.networkArguments, id: self.id, rootPath: self.rootPath, basePath: self.basePath, testingEnvironment: self.testingEnvironment, postbox: self.postbox, network: network)
|
||||
updated.shouldBeServiceTaskMaster.set(self.shouldBeServiceTaskMaster.get())
|
||||
@ -340,7 +340,7 @@ public func accountWithId(networkArguments: NetworkInitializationArguments, id:
|
||||
if let accountState = accountState {
|
||||
switch accountState {
|
||||
case let unauthorizedState as UnauthorizedAccountState:
|
||||
return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: Int(unauthorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: unauthorizedState.isTestingEnvironment, languageCode: localizationSettings?.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil)
|
||||
return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: Int(unauthorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: unauthorizedState.isTestingEnvironment, languageCode: localizationSettings?.primaryComponent.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil)
|
||||
|> map { network -> AccountResult in
|
||||
return .unauthorized(UnauthorizedAccount(networkArguments: networkArguments, id: id, rootPath: rootPath, basePath: path, testingEnvironment: unauthorizedState.isTestingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
|
||||
}
|
||||
@ -349,7 +349,7 @@ public func accountWithId(networkArguments: NetworkInitializationArguments, id:
|
||||
return (transaction.getPeer(authorizedState.peerId) as? TelegramUser)?.phone
|
||||
}
|
||||
|> mapToSignal { phoneNumber in
|
||||
return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: Int(authorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: authorizedState.isTestingEnvironment, languageCode: localizationSettings?.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: phoneNumber)
|
||||
return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: Int(authorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: authorizedState.isTestingEnvironment, languageCode: localizationSettings?.primaryComponent.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: phoneNumber)
|
||||
|> map { network -> AccountResult in
|
||||
return .authorized(Account(id: id, basePath: path, testingEnvironment: authorizedState.isTestingEnvironment, postbox: postbox, network: network, networkArguments: networkArguments, peerId: authorizedState.peerId, auxiliaryMethods: auxiliaryMethods))
|
||||
}
|
||||
@ -359,7 +359,7 @@ public func accountWithId(networkArguments: NetworkInitializationArguments, id:
|
||||
}
|
||||
}
|
||||
|
||||
return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: 2, keychain: keychain, basePath: path, testingEnvironment: beginWithTestingEnvironment, languageCode: localizationSettings?.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil)
|
||||
return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: 2, keychain: keychain, basePath: path, testingEnvironment: beginWithTestingEnvironment, languageCode: localizationSettings?.primaryComponent.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil)
|
||||
|> map { network -> AccountResult in
|
||||
return .unauthorized(UnauthorizedAccount(networkArguments: networkArguments, id: id, rootPath: rootPath, basePath: path, testingEnvironment: beginWithTestingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
|
||||
}
|
||||
@ -963,6 +963,9 @@ public class Account {
|
||||
})
|
||||
self.localInputActivityManager = PeerInputActivityManager()
|
||||
self.accountPresenceManager = AccountPresenceManager(shouldKeepOnlinePresence: self.shouldKeepOnlinePresence.get(), network: network)
|
||||
let _ = (postbox.transaction { transaction -> Void in
|
||||
transaction.updatePeerPresencesInternal([peerId: TelegramUserPresence(status: .present(until: Int32.max - 1))])
|
||||
}).start()
|
||||
self.notificationAutolockReportManager = NotificationAutolockReportManager(deadline: self.autolockReportDeadline.get(), network: network)
|
||||
self.autolockReportDeadline.set(
|
||||
postbox.combinedView(keys: [.accessChallengeData])
|
||||
@ -1128,27 +1131,27 @@ public class Account {
|
||||
}))
|
||||
|
||||
let shouldBeMaster = combineLatest(shouldBeServiceTaskMaster.get(), postbox.isMasterClient())
|
||||
|> map { [weak self] shouldBeMaster, isMaster -> Bool in
|
||||
if shouldBeMaster == .always && !isMaster {
|
||||
self?.postbox.becomeMasterClient()
|
||||
}
|
||||
return (shouldBeMaster == .now || shouldBeMaster == .always) && isMaster
|
||||
|> map { [weak self] shouldBeMaster, isMaster -> Bool in
|
||||
if shouldBeMaster == .always && !isMaster {
|
||||
self?.postbox.becomeMasterClient()
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
return (shouldBeMaster == .now || shouldBeMaster == .always) && isMaster
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|
||||
self.network.shouldKeepConnection.set(shouldBeMaster)
|
||||
self.network.shouldExplicitelyKeepWorkerConnections.set(self.shouldExplicitelyKeepWorkerConnections.get())
|
||||
|
||||
let serviceTasksMaster = shouldBeMaster
|
||||
|> deliverOn(self.serviceQueue)
|
||||
|> mapToSignal { [weak self] value -> Signal<Void, NoError> in
|
||||
if let strongSelf = self, value {
|
||||
Logger.shared.log("Account", "Became master")
|
||||
return managedServiceViews(accountPeerId: peerId, network: strongSelf.network, postbox: strongSelf.postbox, stateManager: strongSelf.stateManager, pendingMessageManager: strongSelf.pendingMessageManager)
|
||||
} else {
|
||||
Logger.shared.log("Account", "Resigned master")
|
||||
return .never()
|
||||
}
|
||||
|> deliverOn(self.serviceQueue)
|
||||
|> mapToSignal { [weak self] value -> Signal<Void, NoError> in
|
||||
if let strongSelf = self, value {
|
||||
Logger.shared.log("Account", "Became master")
|
||||
return managedServiceViews(accountPeerId: peerId, network: strongSelf.network, postbox: strongSelf.postbox, stateManager: strongSelf.stateManager, pendingMessageManager: strongSelf.pendingMessageManager)
|
||||
} else {
|
||||
Logger.shared.log("Account", "Resigned master")
|
||||
return .never()
|
||||
}
|
||||
}
|
||||
self.managedServiceViewsDisposable.set(serviceTasksMaster.start())
|
||||
|
||||
@ -1214,39 +1217,6 @@ public class Account {
|
||||
let settings: CacheStorageSettings = ((view.views[storagePreferencesKey] as? PreferencesView)?.values[PreferencesKeys.cacheStorageSettings] as? CacheStorageSettings) ?? CacheStorageSettings.defaultSettings
|
||||
mediaBox.setMaxStoreTime(settings.defaultCacheStorageTimeout)
|
||||
})
|
||||
|
||||
/*let updatedPresence = self.shouldKeepOnlinePresence.get()
|
||||
|> distinctUntilChanged
|
||||
|> mapToSignal { [weak self] online -> Signal<Void, NoError> in
|
||||
if let strongSelf = self {
|
||||
let delayRequest: Signal<Void, NoError> = .complete()
|
||||
|> delay(60.0, queue: Queue.concurrentDefaultQueue())
|
||||
let pushStatusOnce = strongSelf.network.request(Api.functions.account.updateStatus(offline: online ? .boolFalse : .boolTrue))
|
||||
|> retryRequest
|
||||
|> mapToSignal { _ -> Signal<Void, NoError> in return .complete() }
|
||||
|
||||
let pushStatusRepeatedly = (pushStatusOnce
|
||||
|> then(delayRequest))
|
||||
|> restart
|
||||
|
||||
let peerId = strongSelf.peerId
|
||||
let updatePresenceLocally = strongSelf.postbox.transaction { transaction -> Void in
|
||||
let timestamp: Double
|
||||
if online {
|
||||
timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 + 60.0 * 60.0 * 24.0 * 356.0
|
||||
} else {
|
||||
timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 - 1.0
|
||||
}
|
||||
transaction.updatePeerPresences([peerId: TelegramUserPresence(status: .present(until: Int32(timestamp)))])
|
||||
}
|
||||
return combineLatest(pushStatusRepeatedly, updatePresenceLocally)
|
||||
|> mapToSignal { _ -> Signal<Void, NoError> in return .complete()
|
||||
}
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
self.updatedPresenceDisposable.set(updatedPresence.start())*/
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
||||
@ -172,10 +172,14 @@ public final class AccountStateManager {
|
||||
return .complete()
|
||||
}
|
||||
} else {
|
||||
return network.request(Api.functions.messages.receivedQueue(maxQts: value))
|
||||
|> ignoreValues
|
||||
|> `catch` { _ -> Signal<Never, NoError> in
|
||||
if value == 0 {
|
||||
return .complete()
|
||||
} else {
|
||||
return network.request(Api.functions.messages.receivedQueue(maxQts: value))
|
||||
|> ignoreValues
|
||||
|> `catch` { _ -> Signal<Never, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start())
|
||||
|
||||
@ -416,7 +416,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[182649427] = { return Api.MessageRange.parse_messageRange($0) }
|
||||
dict[946083368] = { return Api.messages.StickerSetInstallResult.parse_stickerSetInstallResultSuccess($0) }
|
||||
dict[904138920] = { return Api.messages.StickerSetInstallResult.parse_stickerSetInstallResultArchive($0) }
|
||||
dict[840162234] = { return Api.Config.parse_config($0) }
|
||||
dict[-422959626] = { return Api.Config.parse_config($0) }
|
||||
dict[-75283823] = { return Api.TopPeerCategoryPeers.parse_topPeerCategoryPeers($0) }
|
||||
dict[-1107729093] = { return Api.Game.parse_game($0) }
|
||||
dict[4883767] = { return Api.SecurePasswordKdfAlgo.parse_securePasswordKdfAlgoUnknown($0) }
|
||||
|
||||
@ -10170,13 +10170,13 @@ extension Api {
|
||||
|
||||
}
|
||||
enum Config: TypeConstructorDescription {
|
||||
case config(flags: Int32, date: Int32, expires: Int32, testMode: Api.Bool, thisDc: Int32, dcOptions: [Api.DcOption], dcTxtDomainName: String, chatSizeMax: Int32, megagroupSizeMax: Int32, forwardedCountMax: Int32, onlineUpdatePeriodMs: Int32, offlineBlurTimeoutMs: Int32, offlineIdleTimeoutMs: Int32, onlineCloudTimeoutMs: Int32, notifyCloudDelayMs: Int32, notifyDefaultDelayMs: Int32, pushChatPeriodMs: Int32, pushChatLimit: Int32, savedGifsLimit: Int32, editTimeLimit: Int32, revokeTimeLimit: Int32, revokePmTimeLimit: Int32, ratingEDecay: Int32, stickersRecentLimit: Int32, stickersFavedLimit: Int32, channelsReadMediaPeriod: Int32, tmpSessions: Int32?, pinnedDialogsCountMax: Int32, callReceiveTimeoutMs: Int32, callRingTimeoutMs: Int32, callConnectTimeoutMs: Int32, callPacketTimeoutMs: Int32, meUrlPrefix: String, autoupdateUrlPrefix: String?, gifSearchUsername: String?, venueSearchUsername: String?, imgSearchUsername: String?, staticMapsProvider: String?, captionLengthMax: Int32, messageLengthMax: Int32, webfileDcId: Int32, suggestedLangCode: String?, langPackVersion: Int32?)
|
||||
case config(flags: Int32, date: Int32, expires: Int32, testMode: Api.Bool, thisDc: Int32, dcOptions: [Api.DcOption], dcTxtDomainName: String, chatSizeMax: Int32, megagroupSizeMax: Int32, forwardedCountMax: Int32, onlineUpdatePeriodMs: Int32, offlineBlurTimeoutMs: Int32, offlineIdleTimeoutMs: Int32, onlineCloudTimeoutMs: Int32, notifyCloudDelayMs: Int32, notifyDefaultDelayMs: Int32, pushChatPeriodMs: Int32, pushChatLimit: Int32, savedGifsLimit: Int32, editTimeLimit: Int32, revokeTimeLimit: Int32, revokePmTimeLimit: Int32, ratingEDecay: Int32, stickersRecentLimit: Int32, stickersFavedLimit: Int32, channelsReadMediaPeriod: Int32, tmpSessions: Int32?, pinnedDialogsCountMax: Int32, callReceiveTimeoutMs: Int32, callRingTimeoutMs: Int32, callConnectTimeoutMs: Int32, callPacketTimeoutMs: Int32, meUrlPrefix: String, autoupdateUrlPrefix: String?, gifSearchUsername: String?, venueSearchUsername: String?, imgSearchUsername: String?, staticMapsProvider: String?, captionLengthMax: Int32, messageLengthMax: Int32, webfileDcId: Int32, suggestedLangCode: String?, langPackVersion: Int32?, baseLangPackVersion: Int32?)
|
||||
|
||||
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .config(let flags, let date, let expires, let testMode, let thisDc, let dcOptions, let dcTxtDomainName, let chatSizeMax, let megagroupSizeMax, let forwardedCountMax, let onlineUpdatePeriodMs, let offlineBlurTimeoutMs, let offlineIdleTimeoutMs, let onlineCloudTimeoutMs, let notifyCloudDelayMs, let notifyDefaultDelayMs, let pushChatPeriodMs, let pushChatLimit, let savedGifsLimit, let editTimeLimit, let revokeTimeLimit, let revokePmTimeLimit, let ratingEDecay, let stickersRecentLimit, let stickersFavedLimit, let channelsReadMediaPeriod, let tmpSessions, let pinnedDialogsCountMax, let callReceiveTimeoutMs, let callRingTimeoutMs, let callConnectTimeoutMs, let callPacketTimeoutMs, let meUrlPrefix, let autoupdateUrlPrefix, let gifSearchUsername, let venueSearchUsername, let imgSearchUsername, let staticMapsProvider, let captionLengthMax, let messageLengthMax, let webfileDcId, let suggestedLangCode, let langPackVersion):
|
||||
case .config(let flags, let date, let expires, let testMode, let thisDc, let dcOptions, let dcTxtDomainName, let chatSizeMax, let megagroupSizeMax, let forwardedCountMax, let onlineUpdatePeriodMs, let offlineBlurTimeoutMs, let offlineIdleTimeoutMs, let onlineCloudTimeoutMs, let notifyCloudDelayMs, let notifyDefaultDelayMs, let pushChatPeriodMs, let pushChatLimit, let savedGifsLimit, let editTimeLimit, let revokeTimeLimit, let revokePmTimeLimit, let ratingEDecay, let stickersRecentLimit, let stickersFavedLimit, let channelsReadMediaPeriod, let tmpSessions, let pinnedDialogsCountMax, let callReceiveTimeoutMs, let callRingTimeoutMs, let callConnectTimeoutMs, let callPacketTimeoutMs, let meUrlPrefix, let autoupdateUrlPrefix, let gifSearchUsername, let venueSearchUsername, let imgSearchUsername, let staticMapsProvider, let captionLengthMax, let messageLengthMax, let webfileDcId, let suggestedLangCode, let langPackVersion, let baseLangPackVersion):
|
||||
if boxed {
|
||||
buffer.appendInt32(840162234)
|
||||
buffer.appendInt32(-422959626)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
@ -10225,14 +10225,15 @@ extension Api {
|
||||
serializeInt32(webfileDcId, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeString(suggestedLangCode!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(langPackVersion!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(baseLangPackVersion!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .config(let flags, let date, let expires, let testMode, let thisDc, let dcOptions, let dcTxtDomainName, let chatSizeMax, let megagroupSizeMax, let forwardedCountMax, let onlineUpdatePeriodMs, let offlineBlurTimeoutMs, let offlineIdleTimeoutMs, let onlineCloudTimeoutMs, let notifyCloudDelayMs, let notifyDefaultDelayMs, let pushChatPeriodMs, let pushChatLimit, let savedGifsLimit, let editTimeLimit, let revokeTimeLimit, let revokePmTimeLimit, let ratingEDecay, let stickersRecentLimit, let stickersFavedLimit, let channelsReadMediaPeriod, let tmpSessions, let pinnedDialogsCountMax, let callReceiveTimeoutMs, let callRingTimeoutMs, let callConnectTimeoutMs, let callPacketTimeoutMs, let meUrlPrefix, let autoupdateUrlPrefix, let gifSearchUsername, let venueSearchUsername, let imgSearchUsername, let staticMapsProvider, let captionLengthMax, let messageLengthMax, let webfileDcId, let suggestedLangCode, let langPackVersion):
|
||||
return ("config", [("flags", flags), ("date", date), ("expires", expires), ("testMode", testMode), ("thisDc", thisDc), ("dcOptions", dcOptions), ("dcTxtDomainName", dcTxtDomainName), ("chatSizeMax", chatSizeMax), ("megagroupSizeMax", megagroupSizeMax), ("forwardedCountMax", forwardedCountMax), ("onlineUpdatePeriodMs", onlineUpdatePeriodMs), ("offlineBlurTimeoutMs", offlineBlurTimeoutMs), ("offlineIdleTimeoutMs", offlineIdleTimeoutMs), ("onlineCloudTimeoutMs", onlineCloudTimeoutMs), ("notifyCloudDelayMs", notifyCloudDelayMs), ("notifyDefaultDelayMs", notifyDefaultDelayMs), ("pushChatPeriodMs", pushChatPeriodMs), ("pushChatLimit", pushChatLimit), ("savedGifsLimit", savedGifsLimit), ("editTimeLimit", editTimeLimit), ("revokeTimeLimit", revokeTimeLimit), ("revokePmTimeLimit", revokePmTimeLimit), ("ratingEDecay", ratingEDecay), ("stickersRecentLimit", stickersRecentLimit), ("stickersFavedLimit", stickersFavedLimit), ("channelsReadMediaPeriod", channelsReadMediaPeriod), ("tmpSessions", tmpSessions), ("pinnedDialogsCountMax", pinnedDialogsCountMax), ("callReceiveTimeoutMs", callReceiveTimeoutMs), ("callRingTimeoutMs", callRingTimeoutMs), ("callConnectTimeoutMs", callConnectTimeoutMs), ("callPacketTimeoutMs", callPacketTimeoutMs), ("meUrlPrefix", meUrlPrefix), ("autoupdateUrlPrefix", autoupdateUrlPrefix), ("gifSearchUsername", gifSearchUsername), ("venueSearchUsername", venueSearchUsername), ("imgSearchUsername", imgSearchUsername), ("staticMapsProvider", staticMapsProvider), ("captionLengthMax", captionLengthMax), ("messageLengthMax", messageLengthMax), ("webfileDcId", webfileDcId), ("suggestedLangCode", suggestedLangCode), ("langPackVersion", langPackVersion)])
|
||||
case .config(let flags, let date, let expires, let testMode, let thisDc, let dcOptions, let dcTxtDomainName, let chatSizeMax, let megagroupSizeMax, let forwardedCountMax, let onlineUpdatePeriodMs, let offlineBlurTimeoutMs, let offlineIdleTimeoutMs, let onlineCloudTimeoutMs, let notifyCloudDelayMs, let notifyDefaultDelayMs, let pushChatPeriodMs, let pushChatLimit, let savedGifsLimit, let editTimeLimit, let revokeTimeLimit, let revokePmTimeLimit, let ratingEDecay, let stickersRecentLimit, let stickersFavedLimit, let channelsReadMediaPeriod, let tmpSessions, let pinnedDialogsCountMax, let callReceiveTimeoutMs, let callRingTimeoutMs, let callConnectTimeoutMs, let callPacketTimeoutMs, let meUrlPrefix, let autoupdateUrlPrefix, let gifSearchUsername, let venueSearchUsername, let imgSearchUsername, let staticMapsProvider, let captionLengthMax, let messageLengthMax, let webfileDcId, let suggestedLangCode, let langPackVersion, let baseLangPackVersion):
|
||||
return ("config", [("flags", flags), ("date", date), ("expires", expires), ("testMode", testMode), ("thisDc", thisDc), ("dcOptions", dcOptions), ("dcTxtDomainName", dcTxtDomainName), ("chatSizeMax", chatSizeMax), ("megagroupSizeMax", megagroupSizeMax), ("forwardedCountMax", forwardedCountMax), ("onlineUpdatePeriodMs", onlineUpdatePeriodMs), ("offlineBlurTimeoutMs", offlineBlurTimeoutMs), ("offlineIdleTimeoutMs", offlineIdleTimeoutMs), ("onlineCloudTimeoutMs", onlineCloudTimeoutMs), ("notifyCloudDelayMs", notifyCloudDelayMs), ("notifyDefaultDelayMs", notifyDefaultDelayMs), ("pushChatPeriodMs", pushChatPeriodMs), ("pushChatLimit", pushChatLimit), ("savedGifsLimit", savedGifsLimit), ("editTimeLimit", editTimeLimit), ("revokeTimeLimit", revokeTimeLimit), ("revokePmTimeLimit", revokePmTimeLimit), ("ratingEDecay", ratingEDecay), ("stickersRecentLimit", stickersRecentLimit), ("stickersFavedLimit", stickersFavedLimit), ("channelsReadMediaPeriod", channelsReadMediaPeriod), ("tmpSessions", tmpSessions), ("pinnedDialogsCountMax", pinnedDialogsCountMax), ("callReceiveTimeoutMs", callReceiveTimeoutMs), ("callRingTimeoutMs", callRingTimeoutMs), ("callConnectTimeoutMs", callConnectTimeoutMs), ("callPacketTimeoutMs", callPacketTimeoutMs), ("meUrlPrefix", meUrlPrefix), ("autoupdateUrlPrefix", autoupdateUrlPrefix), ("gifSearchUsername", gifSearchUsername), ("venueSearchUsername", venueSearchUsername), ("imgSearchUsername", imgSearchUsername), ("staticMapsProvider", staticMapsProvider), ("captionLengthMax", captionLengthMax), ("messageLengthMax", messageLengthMax), ("webfileDcId", webfileDcId), ("suggestedLangCode", suggestedLangCode), ("langPackVersion", langPackVersion), ("baseLangPackVersion", baseLangPackVersion)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -10327,6 +10328,8 @@ extension Api {
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_42 = parseString(reader) }
|
||||
var _43: Int32?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_43 = reader.readInt32() }
|
||||
var _44: Int32?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {_44 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
@ -10370,8 +10373,9 @@ extension Api {
|
||||
let _c41 = _41 != nil
|
||||
let _c42 = (Int(_1!) & Int(1 << 2) == 0) || _42 != nil
|
||||
let _c43 = (Int(_1!) & Int(1 << 2) == 0) || _43 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 && _c29 && _c30 && _c31 && _c32 && _c33 && _c34 && _c35 && _c36 && _c37 && _c38 && _c39 && _c40 && _c41 && _c42 && _c43 {
|
||||
return Api.Config.config(flags: _1!, date: _2!, expires: _3!, testMode: _4!, thisDc: _5!, dcOptions: _6!, dcTxtDomainName: _7!, chatSizeMax: _8!, megagroupSizeMax: _9!, forwardedCountMax: _10!, onlineUpdatePeriodMs: _11!, offlineBlurTimeoutMs: _12!, offlineIdleTimeoutMs: _13!, onlineCloudTimeoutMs: _14!, notifyCloudDelayMs: _15!, notifyDefaultDelayMs: _16!, pushChatPeriodMs: _17!, pushChatLimit: _18!, savedGifsLimit: _19!, editTimeLimit: _20!, revokeTimeLimit: _21!, revokePmTimeLimit: _22!, ratingEDecay: _23!, stickersRecentLimit: _24!, stickersFavedLimit: _25!, channelsReadMediaPeriod: _26!, tmpSessions: _27, pinnedDialogsCountMax: _28!, callReceiveTimeoutMs: _29!, callRingTimeoutMs: _30!, callConnectTimeoutMs: _31!, callPacketTimeoutMs: _32!, meUrlPrefix: _33!, autoupdateUrlPrefix: _34, gifSearchUsername: _35, venueSearchUsername: _36, imgSearchUsername: _37, staticMapsProvider: _38, captionLengthMax: _39!, messageLengthMax: _40!, webfileDcId: _41!, suggestedLangCode: _42, langPackVersion: _43)
|
||||
let _c44 = (Int(_1!) & Int(1 << 2) == 0) || _44 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 && _c29 && _c30 && _c31 && _c32 && _c33 && _c34 && _c35 && _c36 && _c37 && _c38 && _c39 && _c40 && _c41 && _c42 && _c43 && _c44 {
|
||||
return Api.Config.config(flags: _1!, date: _2!, expires: _3!, testMode: _4!, thisDc: _5!, dcOptions: _6!, dcTxtDomainName: _7!, chatSizeMax: _8!, megagroupSizeMax: _9!, forwardedCountMax: _10!, onlineUpdatePeriodMs: _11!, offlineBlurTimeoutMs: _12!, offlineIdleTimeoutMs: _13!, onlineCloudTimeoutMs: _14!, notifyCloudDelayMs: _15!, notifyDefaultDelayMs: _16!, pushChatPeriodMs: _17!, pushChatLimit: _18!, savedGifsLimit: _19!, editTimeLimit: _20!, revokeTimeLimit: _21!, revokePmTimeLimit: _22!, ratingEDecay: _23!, stickersRecentLimit: _24!, stickersFavedLimit: _25!, channelsReadMediaPeriod: _26!, tmpSessions: _27, pinnedDialogsCountMax: _28!, callReceiveTimeoutMs: _29!, callRingTimeoutMs: _30!, callConnectTimeoutMs: _31!, callPacketTimeoutMs: _32!, meUrlPrefix: _33!, autoupdateUrlPrefix: _34, gifSearchUsername: _35, venueSearchUsername: _36, imgSearchUsername: _37, staticMapsProvider: _38, captionLengthMax: _39!, messageLengthMax: _40!, webfileDcId: _41!, suggestedLangCode: _42, langPackVersion: _43, baseLangPackVersion: _44)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
||||
33
TelegramCore/ConfirmTwoStepRecoveryEmail.swift
Normal file
33
TelegramCore/ConfirmTwoStepRecoveryEmail.swift
Normal file
@ -0,0 +1,33 @@
|
||||
import Foundation
|
||||
#if os(macOS)
|
||||
import SwiftSignalKitMac
|
||||
import MtProtoKitMac
|
||||
#else
|
||||
import SwiftSignalKit
|
||||
import MtProtoKitDynamic
|
||||
#endif
|
||||
|
||||
public enum ConfirmTwoStepRecoveryEmailError {
|
||||
case invalidEmail
|
||||
case invalidCode
|
||||
case flood
|
||||
case expired
|
||||
case generic
|
||||
}
|
||||
|
||||
public func confirmTwoStepRecoveryEmail(network: Network, email: String, code: String) -> Signal<Never, ConfirmTwoStepRecoveryEmailError> {
|
||||
return network.request(Api.functions.account.confirmPasswordEmail(email: email, code: code), automaticFloodWait: false)
|
||||
|> mapError { error -> ConfirmTwoStepRecoveryEmailError in
|
||||
if error.errorDescription == "EMAIL_INVALID" {
|
||||
return .invalidEmail
|
||||
} else if error.errorDescription == "CODE_INVALID" {
|
||||
return .invalidCode
|
||||
} else if error.errorDescription == "EMAIL_HASH_EXPIRED" {
|
||||
return .expired
|
||||
} else if error.errorDescription.hasPrefix("FLOOD_WAIT") {
|
||||
return .flood
|
||||
}
|
||||
return .generic
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
@ -8,15 +8,17 @@ import Foundation
|
||||
public final class LocalizationInfo: PostboxCoding {
|
||||
public let languageCode: String
|
||||
public let baseLanguageCode: String?
|
||||
public let customPluralizationCode: String?
|
||||
public let title: String
|
||||
public let localizedTitle: String
|
||||
public let isOfficial: Bool
|
||||
public let totalStringCount: Int32
|
||||
public let translatedStringCount: Int32
|
||||
|
||||
public init(languageCode: String, baseLanguageCode: String?, title: String, localizedTitle: String, isOfficial: Bool, totalStringCount: Int32, translatedStringCount: Int32) {
|
||||
public init(languageCode: String, baseLanguageCode: String?, customPluralizationCode: String?, title: String, localizedTitle: String, isOfficial: Bool, totalStringCount: Int32, translatedStringCount: Int32) {
|
||||
self.languageCode = languageCode
|
||||
self.baseLanguageCode = baseLanguageCode
|
||||
self.customPluralizationCode = customPluralizationCode
|
||||
self.title = title
|
||||
self.localizedTitle = localizedTitle
|
||||
self.isOfficial = isOfficial
|
||||
@ -27,6 +29,7 @@ public final class LocalizationInfo: PostboxCoding {
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.languageCode = decoder.decodeStringForKey("lc", orElse: "")
|
||||
self.baseLanguageCode = decoder.decodeOptionalStringForKey("nlc")
|
||||
self.customPluralizationCode = decoder.decodeOptionalStringForKey("cpc")
|
||||
self.title = decoder.decodeStringForKey("t", orElse: "")
|
||||
self.localizedTitle = decoder.decodeStringForKey("lt", orElse: "")
|
||||
self.isOfficial = decoder.decodeInt32ForKey("of", orElse: 0) != 0
|
||||
@ -41,6 +44,11 @@ public final class LocalizationInfo: PostboxCoding {
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "nlc")
|
||||
}
|
||||
if let customPluralizationCode = self.customPluralizationCode {
|
||||
encoder.encodeString(customPluralizationCode, forKey: "cpc")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "cpc")
|
||||
}
|
||||
encoder.encodeString(self.title, forKey: "t")
|
||||
encoder.encodeString(self.localizedTitle, forKey: "lt")
|
||||
encoder.encodeInt32(self.isOfficial ? 1 : 0, forKey: "of")
|
||||
@ -53,7 +61,7 @@ extension LocalizationInfo {
|
||||
convenience init(apiLanguage: Api.LangPackLanguage) {
|
||||
switch apiLanguage {
|
||||
case let .langPackLanguage(language):
|
||||
self.init(languageCode: language.langCode, baseLanguageCode: nil/*language.baseLangCode*/, title: language.name, localizedTitle: language.nativeName, isOfficial: true/*(language.flags & (1 << 0)) != 0*/, totalStringCount: 1/*language.stringsCount*/, translatedStringCount: 1/*language.translatedCount*/)
|
||||
self.init(languageCode: language.langCode, baseLanguageCode: language.baseLangCode, customPluralizationCode: language.pluralCode, title: language.name, localizedTitle: language.nativeName, isOfficial: (language.flags & (1 << 0)) != 0, totalStringCount: language.stringsCount, translatedStringCount: language.translatedCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,13 +12,12 @@ public enum RequestLocalizationPreviewError {
|
||||
case generic
|
||||
}
|
||||
|
||||
public func requestLocalizationPreview(postbox: Postbox, network: Network, identifier: String) -> Signal<LocalizationInfo, RequestLocalizationPreviewError> {
|
||||
return .never()
|
||||
/*return network.request(Api.functions.langpack.getLanguage(langPack: "", langCode: identifier))
|
||||
public func requestLocalizationPreview(network: Network, identifier: String) -> Signal<LocalizationInfo, RequestLocalizationPreviewError> {
|
||||
return network.request(Api.functions.langpack.getLanguage(langPack: "", langCode: identifier))
|
||||
|> mapError { _ -> RequestLocalizationPreviewError in
|
||||
return .generic
|
||||
}
|
||||
|> map { language -> LocalizationInfo in
|
||||
return LocalizationInfo(apiLanguage: language)
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,23 +5,73 @@ import Foundation
|
||||
import Postbox
|
||||
#endif
|
||||
|
||||
public final class LocalizationSettings: PreferencesEntry, Equatable {
|
||||
public final class LocalizationComponent: Equatable, PostboxCoding {
|
||||
public let languageCode: String
|
||||
public let localization: Localization
|
||||
public let customPluralizationCode: String?
|
||||
|
||||
public init(languageCode: String, localization: Localization) {
|
||||
public init(languageCode: String, localization: Localization, customPluralizationCode: String?) {
|
||||
self.languageCode = languageCode
|
||||
self.localization = localization
|
||||
self.customPluralizationCode = customPluralizationCode
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.languageCode = decoder.decodeStringForKey("lc", orElse: "en")
|
||||
self.languageCode = decoder.decodeStringForKey("lc", orElse: "")
|
||||
self.localization = decoder.decodeObjectForKey("loc", decoder: { Localization(decoder: $0) }) as! Localization
|
||||
self.customPluralizationCode = decoder.decodeOptionalStringForKey("cpl")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeString(self.languageCode, forKey: "lc")
|
||||
encoder.encodeObject(self.localization, forKey: "loc")
|
||||
if let customPluralizationCode = self.customPluralizationCode {
|
||||
encoder.encodeString(customPluralizationCode, forKey: "cpl")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "cpl")
|
||||
}
|
||||
}
|
||||
|
||||
public static func ==(lhs: LocalizationComponent, rhs: LocalizationComponent) -> Bool {
|
||||
if lhs.languageCode != rhs.languageCode {
|
||||
return false
|
||||
}
|
||||
if lhs.localization != rhs.localization {
|
||||
return false
|
||||
}
|
||||
if lhs.customPluralizationCode != rhs.customPluralizationCode {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public final class LocalizationSettings: PreferencesEntry, Equatable {
|
||||
public let primaryComponent: LocalizationComponent
|
||||
public let secondaryComponent: LocalizationComponent?
|
||||
|
||||
public init(primaryComponent: LocalizationComponent, secondaryComponent: LocalizationComponent?) {
|
||||
self.primaryComponent = primaryComponent
|
||||
self.secondaryComponent = secondaryComponent
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
if let languageCode = decoder.decodeOptionalStringForKey("lc") {
|
||||
self.primaryComponent = LocalizationComponent(languageCode: languageCode, localization: decoder.decodeObjectForKey("loc", decoder: { Localization(decoder: $0) }) as! Localization, customPluralizationCode: nil)
|
||||
self.secondaryComponent = nil
|
||||
} else {
|
||||
self.primaryComponent = decoder.decodeObjectForKey("primaryComponent", decoder: { LocalizationComponent(decoder: $0) }) as! LocalizationComponent
|
||||
self.secondaryComponent = decoder.decodeObjectForKey("secondaryComponent", decoder: { LocalizationComponent(decoder: $0) }) as? LocalizationComponent
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeObject(self.primaryComponent, forKey: "primaryComponent")
|
||||
if let secondaryComponent = self.secondaryComponent {
|
||||
encoder.encodeObject(secondaryComponent, forKey: "secondaryComponent")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "secondaryComponent")
|
||||
}
|
||||
}
|
||||
|
||||
public func isEqual(to: PreferencesEntry) -> Bool {
|
||||
@ -33,6 +83,6 @@ public final class LocalizationSettings: PreferencesEntry, Equatable {
|
||||
}
|
||||
|
||||
public static func ==(lhs: LocalizationSettings, rhs: LocalizationSettings) -> Bool {
|
||||
return lhs.languageCode == rhs.languageCode && lhs.localization == rhs.localization
|
||||
return lhs.primaryComponent == rhs.primaryComponent && lhs.secondaryComponent == rhs.secondaryComponent
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,35 +114,53 @@ public func downloadLocalization(network: Network, languageCode: String) -> Sign
|
||||
}
|
||||
}
|
||||
|
||||
public enum DownoadAndApplyLocalizationError {
|
||||
public enum DownloadAndApplyLocalizationError {
|
||||
case generic
|
||||
}
|
||||
|
||||
public func downoadAndApplyLocalization(postbox: Postbox, network: Network, languageCode: String) -> Signal<Void, DownoadAndApplyLocalizationError> {
|
||||
return downloadLocalization(network: network, languageCode: languageCode)
|
||||
|> mapError { _ -> DownoadAndApplyLocalizationError in
|
||||
public func downloadAndApplyLocalization(postbox: Postbox, network: Network, languageCode: String) -> Signal<Void, DownloadAndApplyLocalizationError> {
|
||||
return requestLocalizationPreview(network: network, identifier: languageCode)
|
||||
|> mapError { _ -> DownloadAndApplyLocalizationError in
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { language -> Signal<Void, DownoadAndApplyLocalizationError> in
|
||||
return postbox.transaction { transaction -> Signal<Void, DownoadAndApplyLocalizationError> in
|
||||
transaction.updatePreferencesEntry(key: PreferencesKeys.localizationSettings, { _ in
|
||||
return LocalizationSettings(languageCode: languageCode, localization: language)
|
||||
})
|
||||
|
||||
network.context.updateApiEnvironment { current in
|
||||
return current?.withUpdatedLangPackCode(languageCode)
|
||||
}
|
||||
|
||||
return network.request(Api.functions.help.test())
|
||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
|> mapToSignal { _ -> Signal<Void, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
|> introduceError(DownoadAndApplyLocalizationError.self)
|
||||
|> mapToSignal { preview -> Signal<Void, DownloadAndApplyLocalizationError> in
|
||||
var primaryAndSecondaryLocalizations: [Signal<Localization, DownloadLocalizationError>] = []
|
||||
primaryAndSecondaryLocalizations.append(downloadLocalization(network: network, languageCode: preview.languageCode))
|
||||
if let secondaryCode = preview.baseLanguageCode {
|
||||
primaryAndSecondaryLocalizations.append(downloadLocalization(network: network, languageCode: secondaryCode))
|
||||
}
|
||||
return combineLatest(primaryAndSecondaryLocalizations)
|
||||
|> mapError { _ -> DownloadAndApplyLocalizationError in
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { components -> Signal<Void, DownloadAndApplyLocalizationError> in
|
||||
guard let primaryLocalization = components.first else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
var secondaryComponent: LocalizationComponent?
|
||||
if let secondaryCode = preview.baseLanguageCode, components.count > 1 {
|
||||
secondaryComponent = LocalizationComponent(languageCode: secondaryCode, localization: components[1], customPluralizationCode: nil)
|
||||
}
|
||||
return postbox.transaction { transaction -> Signal<Void, DownloadAndApplyLocalizationError> in
|
||||
transaction.updatePreferencesEntry(key: PreferencesKeys.localizationSettings, { _ in
|
||||
return LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: preview.languageCode, localization: primaryLocalization, customPluralizationCode: preview.customPluralizationCode), secondaryComponent: secondaryComponent)
|
||||
})
|
||||
|
||||
network.context.updateApiEnvironment { current in
|
||||
return current?.withUpdatedLangPackCode(preview.languageCode)
|
||||
}
|
||||
|
||||
return network.request(Api.functions.help.test())
|
||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
|> mapToSignal { _ -> Signal<Void, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
|> introduceError(DownloadAndApplyLocalizationError.self)
|
||||
}
|
||||
|> introduceError(DownloadAndApplyLocalizationError.self)
|
||||
|> switchToLatest
|
||||
}
|
||||
|> introduceError(DownoadAndApplyLocalizationError.self)
|
||||
|> switchToLatest
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,8 +68,17 @@ func managedConfigurationUpdates(postbox: Postbox, network: Network) -> Signal<V
|
||||
return configuration
|
||||
})
|
||||
|
||||
let (_, version, _) = getLocalization(transaction)
|
||||
if version != config.langPackVersion {
|
||||
let (primary, secondary) = getLocalization(transaction)
|
||||
var invalidateLocalization = false
|
||||
if primary.version != config.langPackVersion {
|
||||
invalidateLocalization = true
|
||||
}
|
||||
if let secondary = secondary, let baseLangPackVersion = config.baseLangPackVersion {
|
||||
if secondary.version != baseLangPackVersion {
|
||||
invalidateLocalization = true
|
||||
}
|
||||
}
|
||||
if invalidateLocalization {
|
||||
addSynchronizeLocalizationUpdatesOperation(transaction: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,7 +120,7 @@ private enum SynchronizeLocalizationUpdatesError {
|
||||
case reset
|
||||
}
|
||||
|
||||
func getLocalization(_ transaction: Transaction) -> (String, Int32, [LocalizationEntry]) {
|
||||
func getLocalization(_ transaction: Transaction) -> (primary: (code: String, version: Int32, entries: [LocalizationEntry]), secondary: (code: String, version: Int32, entries: [LocalizationEntry])?) {
|
||||
let localizationSettings: LocalizationSettings?
|
||||
if let current = transaction.getPreferencesEntry(key: PreferencesKeys.localizationSettings) as? LocalizationSettings {
|
||||
localizationSettings = current
|
||||
@ -128,76 +128,98 @@ func getLocalization(_ transaction: Transaction) -> (String, Int32, [Localizatio
|
||||
localizationSettings = nil
|
||||
}
|
||||
if let localizationSettings = localizationSettings {
|
||||
return (localizationSettings.languageCode, localizationSettings.localization.version, localizationSettings.localization.entries)
|
||||
return (primary: (localizationSettings.primaryComponent.languageCode, localizationSettings.primaryComponent.localization.version, localizationSettings.primaryComponent.localization.entries), secondary: localizationSettings.secondaryComponent.flatMap({ ($0.languageCode, $0.localization.version, $0.localization.entries) }))
|
||||
} else {
|
||||
return ("en", 0, [])
|
||||
return (primary: ("en", 0, []), secondary: nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func parseLangPackDifference(_ difference: Api.LangPackDifference) -> (code: String, fromVersion: Int32, version: Int32, entries: [LocalizationEntry]) {
|
||||
switch difference {
|
||||
case let .langPackDifference(code, fromVersion, version, strings):
|
||||
var entries: [LocalizationEntry] = []
|
||||
for string in strings {
|
||||
switch string {
|
||||
case let .langPackString(key, value):
|
||||
entries.append(.string(key: key, value: value))
|
||||
case let .langPackStringPluralized(_, key, zeroValue, oneValue, twoValue, fewValue, manyValue, otherValue):
|
||||
entries.append(.pluralizedString(key: key, zero: zeroValue, one: oneValue, two: twoValue, few: fewValue, many: manyValue, other: otherValue))
|
||||
case let .langPackStringDeleted(key):
|
||||
entries.append(.string(key: key, value: ""))
|
||||
}
|
||||
}
|
||||
return (code, fromVersion, version, entries)
|
||||
}
|
||||
}
|
||||
|
||||
private func synchronizeLocalizationUpdates(transaction: Transaction, postbox: Postbox, network: Network) -> Signal<Void, NoError> {
|
||||
let currentLanguageAndVersion = postbox.transaction { transaction -> (String, Int32) in
|
||||
let (code, version, _) = getLocalization(transaction)
|
||||
return (code, version)
|
||||
let currentLanguageAndVersion = postbox.transaction { transaction -> (primary: (code: String, version: Int32), secondary: (code: String, version: Int32)?) in
|
||||
let (primary, secondary) = getLocalization(transaction)
|
||||
return ((primary.code, primary.version), secondary.flatMap({ ($0.code, $0.version) }))
|
||||
}
|
||||
|
||||
let poll = currentLanguageAndVersion
|
||||
|> mapError { _ -> SynchronizeLocalizationUpdatesError in return .done }
|
||||
|> mapToSignal { (languageCode, fromVersion) -> Signal<Void, SynchronizeLocalizationUpdatesError> in
|
||||
return network.request(Api.functions.langpack.getDifference(langCode: languageCode, fromVersion: fromVersion))
|
||||
|> mapError { _ -> SynchronizeLocalizationUpdatesError in return .reset }
|
||||
|> mapToSignal { result -> Signal<Void, SynchronizeLocalizationUpdatesError> in
|
||||
let updatedCode: String
|
||||
let updatedVersion: Int32
|
||||
var updatedEntries: [LocalizationEntry] = []
|
||||
switch result {
|
||||
case let .langPackDifference(code, _, versionValue, strings):
|
||||
updatedCode = code
|
||||
updatedVersion = versionValue
|
||||
for string in strings {
|
||||
switch string {
|
||||
case let .langPackString(key, value):
|
||||
updatedEntries.append(.string(key: key, value: value))
|
||||
case let .langPackStringPluralized(_, key, zeroValue, oneValue, twoValue, fewValue, manyValue, otherValue):
|
||||
updatedEntries.append(.pluralizedString(key: key, zero: zeroValue, one: oneValue, two: twoValue, few: fewValue, many: manyValue, other: otherValue))
|
||||
case let .langPackStringDeleted(key):
|
||||
updatedEntries.append(.string(key: key, value: ""))
|
||||
}
|
||||
}
|
||||
}
|
||||
|> introduceError(SynchronizeLocalizationUpdatesError.self)
|
||||
|> mapToSignal { (primary, secondary) -> Signal<Void, SynchronizeLocalizationUpdatesError> in
|
||||
var differences: [Signal<Api.LangPackDifference, MTRpcError>] = []
|
||||
differences.append(network.request(Api.functions.langpack.getDifference(langCode: primary.code, fromVersion: primary.version)))
|
||||
if let secondary = secondary {
|
||||
differences.append(network.request(Api.functions.langpack.getDifference(langCode: secondary.code, fromVersion: secondary.version)))
|
||||
}
|
||||
|
||||
return combineLatest(differences)
|
||||
|> mapError { _ -> SynchronizeLocalizationUpdatesError in return .reset }
|
||||
|> mapToSignal { differences -> Signal<Void, SynchronizeLocalizationUpdatesError> in
|
||||
let parsedDifferences = differences.map(parseLangPackDifference)
|
||||
return postbox.transaction { transaction -> Signal<Void, SynchronizeLocalizationUpdatesError> in
|
||||
let (primary, secondary) = getLocalization(transaction)
|
||||
|
||||
return postbox.transaction { transaction -> Signal<Void, SynchronizeLocalizationUpdatesError> in
|
||||
let (code, version, entries) = getLocalization(transaction)
|
||||
|
||||
if code == updatedCode {
|
||||
if fromVersion == version {
|
||||
var updatedEntryKeys = Set<String>()
|
||||
for entry in updatedEntries {
|
||||
updatedEntryKeys.insert(entry.key)
|
||||
}
|
||||
|
||||
var mergedEntries: [LocalizationEntry] = []
|
||||
for entry in entries {
|
||||
if !updatedEntryKeys.contains(entry.key) {
|
||||
mergedEntries.append(entry)
|
||||
}
|
||||
}
|
||||
mergedEntries.append(contentsOf: updatedEntries)
|
||||
|
||||
transaction.setPreferencesEntry(key: PreferencesKeys.localizationSettings, value: LocalizationSettings(languageCode: updatedCode, localization: Localization(version: updatedVersion, entries: mergedEntries)))
|
||||
|
||||
return .fail(.done)
|
||||
} else {
|
||||
var currentSettings = transaction.getPreferencesEntry(key: PreferencesKeys.localizationSettings) as? LocalizationSettings ?? LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: "en", localization: Localization(version: 0, entries: []), customPluralizationCode: nil), secondaryComponent: nil)
|
||||
|
||||
for difference in parsedDifferences {
|
||||
let current: (isPrimary: Bool, entries: [LocalizationEntry])
|
||||
if difference.code == primary.code {
|
||||
if primary.version != difference.fromVersion {
|
||||
return .complete()
|
||||
}
|
||||
current = (true, primary.entries)
|
||||
} else if let secondary = secondary, difference.code == secondary.code {
|
||||
if secondary.version != difference.fromVersion {
|
||||
return .complete()
|
||||
}
|
||||
current = (false, secondary.entries)
|
||||
} else {
|
||||
return .fail(.reset)
|
||||
}
|
||||
|
||||
var updatedEntryKeys = Set<String>()
|
||||
for entry in difference.entries {
|
||||
updatedEntryKeys.insert(entry.key)
|
||||
}
|
||||
|
||||
var mergedEntries: [LocalizationEntry] = []
|
||||
for entry in current.entries {
|
||||
if !updatedEntryKeys.contains(entry.key) {
|
||||
mergedEntries.append(entry)
|
||||
}
|
||||
}
|
||||
mergedEntries.append(contentsOf: difference.entries)
|
||||
if current.isPrimary {
|
||||
currentSettings = LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: currentSettings.primaryComponent.languageCode, localization: Localization(version: difference.version, entries: mergedEntries), customPluralizationCode: currentSettings.primaryComponent.customPluralizationCode), secondaryComponent: currentSettings.secondaryComponent)
|
||||
} else if let currentSecondary = currentSettings.secondaryComponent {
|
||||
currentSettings = LocalizationSettings(primaryComponent: currentSettings.primaryComponent, secondaryComponent: LocalizationComponent(languageCode: currentSecondary.languageCode, localization: Localization(version: difference.version, entries: mergedEntries), customPluralizationCode: currentSecondary.customPluralizationCode))
|
||||
}
|
||||
}
|
||||
|> mapError { _ -> SynchronizeLocalizationUpdatesError in return .reset
|
||||
}
|
||||
|> switchToLatest
|
||||
|
||||
transaction.setPreferencesEntry(key: PreferencesKeys.localizationSettings, value: currentSettings)
|
||||
return .fail(.done)
|
||||
}
|
||||
|> mapError { _ -> SynchronizeLocalizationUpdatesError in
|
||||
return .reset
|
||||
}
|
||||
|> switchToLatest
|
||||
}
|
||||
}
|
||||
|
||||
return ((poll
|
||||
|> `catch` { error -> Signal<Void, Void> in
|
||||
@ -206,8 +228,8 @@ private func synchronizeLocalizationUpdates(transaction: Transaction, postbox: P
|
||||
return .fail(Void())
|
||||
case .reset:
|
||||
return postbox.transaction { transaction -> Signal<Void, Void> in
|
||||
let (code, _, _) = getLocalization(transaction)
|
||||
return downoadAndApplyLocalization(postbox: postbox, network: network, languageCode: code)
|
||||
let (primary, _) = getLocalization(transaction)
|
||||
return downloadAndApplyLocalization(postbox: postbox, network: network, languageCode: primary.code)
|
||||
|> mapError { _ -> Void in
|
||||
return Void()
|
||||
}
|
||||
@ -221,41 +243,61 @@ private func synchronizeLocalizationUpdates(transaction: Transaction, postbox: P
|
||||
}
|
||||
|
||||
func tryApplyingLanguageDifference(transaction: Transaction, langCode: String, difference: Api.LangPackDifference) -> Bool {
|
||||
let (code, version, entries) = getLocalization(transaction)
|
||||
let (primary, secondary) = getLocalization(transaction)
|
||||
switch difference {
|
||||
case let .langPackDifference(updatedCode, fromVersion, updatedVersion, strings):
|
||||
if fromVersion == version && updatedCode == code {
|
||||
var updatedEntries: [LocalizationEntry] = []
|
||||
|
||||
for string in strings {
|
||||
switch string {
|
||||
case let .langPackString(key, value):
|
||||
updatedEntries.append(.string(key: key, value: value))
|
||||
case let .langPackStringPluralized(_, key, zeroValue, oneValue, twoValue, fewValue, manyValue, otherValue):
|
||||
updatedEntries.append(.pluralizedString(key: key, zero: zeroValue, one: oneValue, two: twoValue, few: fewValue, many: manyValue, other: otherValue))
|
||||
case let .langPackStringDeleted(key):
|
||||
updatedEntries.append(.string(key: key, value: ""))
|
||||
}
|
||||
}
|
||||
|
||||
var updatedEntryKeys = Set<String>()
|
||||
for entry in updatedEntries {
|
||||
updatedEntryKeys.insert(entry.key)
|
||||
}
|
||||
|
||||
var mergedEntries: [LocalizationEntry] = []
|
||||
for entry in entries {
|
||||
if !updatedEntryKeys.contains(entry.key) {
|
||||
mergedEntries.append(entry)
|
||||
}
|
||||
}
|
||||
mergedEntries.append(contentsOf: updatedEntries)
|
||||
|
||||
transaction.setPreferencesEntry(key: PreferencesKeys.localizationSettings, value: LocalizationSettings(languageCode: updatedCode, localization: Localization(version: updatedVersion, entries: mergedEntries)))
|
||||
|
||||
return true
|
||||
} else {
|
||||
var current: (isPrimary: Bool, version: Int32, entries: [LocalizationEntry])?
|
||||
if updatedCode == primary.code {
|
||||
current = (true, primary.version, primary.entries)
|
||||
} else if let secondary = secondary, secondary.code == updatedCode {
|
||||
current = (false, secondary.version, secondary.entries)
|
||||
}
|
||||
guard let (isPrimary, version, entries) = current else {
|
||||
return false
|
||||
}
|
||||
guard fromVersion == version else {
|
||||
return false
|
||||
}
|
||||
var updatedEntries: [LocalizationEntry] = []
|
||||
|
||||
for string in strings {
|
||||
switch string {
|
||||
case let .langPackString(key, value):
|
||||
updatedEntries.append(.string(key: key, value: value))
|
||||
case let .langPackStringPluralized(_, key, zeroValue, oneValue, twoValue, fewValue, manyValue, otherValue):
|
||||
updatedEntries.append(.pluralizedString(key: key, zero: zeroValue, one: oneValue, two: twoValue, few: fewValue, many: manyValue, other: otherValue))
|
||||
case let .langPackStringDeleted(key):
|
||||
updatedEntries.append(.string(key: key, value: ""))
|
||||
}
|
||||
}
|
||||
|
||||
var updatedEntryKeys = Set<String>()
|
||||
for entry in updatedEntries {
|
||||
updatedEntryKeys.insert(entry.key)
|
||||
}
|
||||
|
||||
var mergedEntries: [LocalizationEntry] = []
|
||||
for entry in entries {
|
||||
if !updatedEntryKeys.contains(entry.key) {
|
||||
mergedEntries.append(entry)
|
||||
}
|
||||
}
|
||||
mergedEntries.append(contentsOf: updatedEntries)
|
||||
|
||||
let currentSettings = transaction.getPreferencesEntry(key: PreferencesKeys.localizationSettings) as? LocalizationSettings ?? LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: "en", localization: Localization(version: 0, entries: []), customPluralizationCode: nil), secondaryComponent: nil)
|
||||
|
||||
var updatedSettings: LocalizationSettings
|
||||
if isPrimary {
|
||||
updatedSettings = LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: currentSettings.primaryComponent.languageCode, localization: Localization(version: updatedVersion, entries: mergedEntries), customPluralizationCode: currentSettings.primaryComponent.customPluralizationCode), secondaryComponent: currentSettings.secondaryComponent)
|
||||
} else if let currentSecondary = currentSettings.secondaryComponent {
|
||||
updatedSettings = LocalizationSettings(primaryComponent: currentSettings.primaryComponent, secondaryComponent: LocalizationComponent(languageCode: currentSecondary.languageCode, localization: Localization(version: updatedVersion, entries: mergedEntries), customPluralizationCode: currentSecondary.customPluralizationCode))
|
||||
} else {
|
||||
assertionFailure()
|
||||
return false
|
||||
}
|
||||
|
||||
transaction.setPreferencesEntry(key: PreferencesKeys.localizationSettings, value: updatedSettings)
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,23 +10,23 @@ import Foundation
|
||||
#endif
|
||||
|
||||
public enum TwoStepVerificationConfiguration {
|
||||
case notSet(pendingEmailPattern: String)
|
||||
case set(hint: String, hasRecoveryEmail: Bool, pendingEmailPattern: String, hasSecureValues: Bool)
|
||||
case notSet(pendingEmail: TwoStepVerificationPendingEmail?)
|
||||
case set(hint: String, hasRecoveryEmail: Bool, pendingEmail: TwoStepVerificationPendingEmail?, hasSecureValues: Bool)
|
||||
}
|
||||
|
||||
public func twoStepVerificationConfiguration(account: Account) -> Signal<TwoStepVerificationConfiguration, NoError> {
|
||||
return account.network.request(Api.functions.account.getPassword())
|
||||
|> retryRequest
|
||||
|> map { result -> TwoStepVerificationConfiguration in
|
||||
switch result {
|
||||
case let .password(password):
|
||||
if password.currentAlgo != nil {
|
||||
return .set(hint: password.hint ?? "", hasRecoveryEmail: (password.flags & (1 << 0)) != 0, pendingEmailPattern: password.emailUnconfirmedPattern ?? "", hasSecureValues: (password.flags & (1 << 1)) != 0)
|
||||
} else {
|
||||
return .notSet(pendingEmailPattern: password.emailUnconfirmedPattern ?? "")
|
||||
}
|
||||
}
|
||||
|> retryRequest
|
||||
|> map { result -> TwoStepVerificationConfiguration in
|
||||
switch result {
|
||||
case let .password(password):
|
||||
if password.currentAlgo != nil {
|
||||
return .set(hint: password.hint ?? "", hasRecoveryEmail: (password.flags & (1 << 0)) != 0, pendingEmail: password.emailUnconfirmedPattern.flatMap({ TwoStepVerificationPendingEmail(pattern: $0, codeLength: nil) }), hasSecureValues: (password.flags & (1 << 1)) != 0)
|
||||
} else {
|
||||
return .notSet(pendingEmail: password.emailUnconfirmedPattern.flatMap({ TwoStepVerificationPendingEmail(pattern: $0, codeLength: nil) }))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct TwoStepVerificationSecureSecret {
|
||||
@ -97,6 +97,11 @@ public enum UpdateTwoStepVerificationPasswordError {
|
||||
public struct TwoStepVerificationPendingEmail {
|
||||
public let pattern: String
|
||||
public let codeLength: Int32?
|
||||
|
||||
public init(pattern: String, codeLength: Int32?) {
|
||||
self.pattern = pattern
|
||||
self.codeLength = codeLength
|
||||
}
|
||||
}
|
||||
|
||||
public enum UpdateTwoStepVerificationPasswordResult {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user