2022-05-29 02:09:25 +04:00

166 lines
8.8 KiB
Swift

import Foundation
import Postbox
import TelegramApi
import SwiftSignalKit
func _internal_currentlySuggestedLocalization(network: Network, extractKeys: [String]) -> Signal<SuggestedLocalizationInfo?, NoError> {
return network.request(Api.functions.help.getConfig())
|> retryRequest
|> mapToSignal { result -> Signal<SuggestedLocalizationInfo?, NoError> in
switch result {
case let .config(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, suggestedLangCode, _, _):
if let suggestedLangCode = suggestedLangCode {
return _internal_suggestedLocalizationInfo(network: network, languageCode: suggestedLangCode, extractKeys: extractKeys) |> map(Optional.init)
} else {
return .single(nil)
}
}
}
}
func _internal_suggestedLocalizationInfo(network: Network, languageCode: String, extractKeys: [String]) -> Signal<SuggestedLocalizationInfo, NoError> {
return combineLatest(network.request(Api.functions.langpack.getLanguages(langPack: "")), network.request(Api.functions.langpack.getStrings(langPack: "", langCode: languageCode, keys: extractKeys)))
|> retryRequest
|> map { languages, strings -> SuggestedLocalizationInfo in
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: ""))
}
}
let infos: [LocalizationInfo] = languages.map(LocalizationInfo.init(apiLanguage:))
return SuggestedLocalizationInfo(languageCode: languageCode, extractedEntries: entries, availableLocalizations: infos)
}
}
func _internal_availableLocalizations(postbox: Postbox, network: Network, allowCached: Bool) -> Signal<[LocalizationInfo], NoError> {
let cached: Signal<[LocalizationInfo], NoError>
if allowCached {
cached = postbox.transaction { transaction -> Signal<[LocalizationInfo], NoError> in
if let entry = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedAvailableLocalizations, key: ValueBoxKey(length: 0)))?.get(CachedLocalizationInfos.self) {
return .single(entry.list)
}
return .complete()
} |> switchToLatest
} else {
cached = .complete()
}
let remote = network.request(Api.functions.langpack.getLanguages(langPack: ""))
|> retryRequest
|> mapToSignal { languages -> Signal<[LocalizationInfo], NoError> in
let infos: [LocalizationInfo] = languages.map(LocalizationInfo.init(apiLanguage:))
return postbox.transaction { transaction -> [LocalizationInfo] in
if let entry = CodableEntry(CachedLocalizationInfos(list: infos)) {
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedAvailableLocalizations, key: ValueBoxKey(length: 0)), entry: entry)
}
return infos
}
}
return cached |> then(remote)
}
public enum DownloadLocalizationError {
case generic
}
func _internal_downloadLocalization(network: Network, languageCode: String) -> Signal<Localization, DownloadLocalizationError> {
return network.request(Api.functions.langpack.getLangPack(langPack: "", langCode: languageCode))
|> mapError { _ -> DownloadLocalizationError in
return .generic
}
|> map { result -> Localization in
let version: Int32
var entries: [LocalizationEntry] = []
switch result {
case let .langPackDifference(_, _, versionValue, strings):
version = versionValue
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 Localization(version: version, entries: entries)
}
}
public enum DownloadAndApplyLocalizationError {
case generic
}
func _internal_downloadAndApplyLocalization(accountManager: AccountManager<TelegramAccountManagerTypes>, postbox: Postbox, network: Network, languageCode: String) -> Signal<Void, DownloadAndApplyLocalizationError> {
return _internal_requestLocalizationPreview(network: network, identifier: languageCode)
|> mapError { _ -> DownloadAndApplyLocalizationError in
return .generic
}
|> mapToSignal { preview -> Signal<Void, DownloadAndApplyLocalizationError> in
var primaryAndSecondaryLocalizations: [Signal<Localization, DownloadLocalizationError>] = []
primaryAndSecondaryLocalizations.append(_internal_downloadLocalization(network: network, languageCode: preview.languageCode))
if let secondaryCode = preview.baseLanguageCode {
primaryAndSecondaryLocalizations.append(_internal_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, localizedName: "", localization: components[1], customPluralizationCode: nil)
}
return accountManager.transaction { transaction -> Signal<Void, DownloadAndApplyLocalizationError> in
transaction.updateSharedData(SharedDataKeys.localizationSettings, { _ in
return PreferencesEntry(LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: preview.languageCode, localizedName: preview.localizedTitle, localization: primaryLocalization, customPluralizationCode: preview.customPluralizationCode), secondaryComponent: secondaryComponent))
})
return postbox.transaction { transaction -> Signal<Void, DownloadAndApplyLocalizationError> in
updateLocalizationListStateInteractively(transaction: transaction, { state in
var state = state
for i in 0 ..< state.availableSavedLocalizations.count {
if state.availableSavedLocalizations[i].languageCode == preview.languageCode {
state.availableSavedLocalizations.remove(at: i)
break
}
}
state.availableSavedLocalizations.insert(preview, at: 0)
return state
})
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()
}
|> castError(DownloadAndApplyLocalizationError.self)
}
|> castError(DownloadAndApplyLocalizationError.self)
|> switchToLatest
}
|> castError(DownloadAndApplyLocalizationError.self)
|> switchToLatest
}
}
}