Swiftgram/submodules/SettingsUI/Sources/Language Selection/TranslatonSettingsController.swift
Ilya Laktyushin 74cd2b6093 Various fixes
2023-01-27 19:53:44 +04:00

204 lines
8.8 KiB
Swift

import Foundation
import UIKit
import Display
import SwiftSignalKit
import Postbox
import TelegramCore
import TelegramPresentationData
import TelegramUIPreferences
import ItemListUI
import PresentationDataUtils
import TelegramStringFormatting
import AccountContext
import TranslateUI
private final class TranslationSettingsControllerArguments {
let context: AccountContext
let updateLanguageSelected: (String, Bool) -> Void
init(context: AccountContext, updateLanguageSelected: @escaping (String, Bool) -> Void) {
self.context = context
self.updateLanguageSelected = updateLanguageSelected
}
}
private enum TranslationSettingsControllerSection: Int32 {
case languages
}
private enum TranslationSettingsControllerEntry: ItemListNodeEntry {
case language(Int32, PresentationTheme, String, String, Bool, String)
var section: ItemListSectionId {
switch self {
case .language:
return TranslationSettingsControllerSection.languages.rawValue
}
}
var stableId: Int32 {
switch self {
case let .language(index, _, _, _, _, _):
return index
}
}
static func ==(lhs: TranslationSettingsControllerEntry, rhs: TranslationSettingsControllerEntry) -> Bool {
switch lhs {
case let .language(lhsIndex, lhsTheme, lhsTitle, lhsSubtitle, lhsValue, lhsCode):
if case let .language(rhsIndex, rhsTheme, rhsTitle, rhsSubtitle, rhsValue, rhsCode) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsTitle == rhsTitle, lhsSubtitle == rhsSubtitle, lhsValue == rhsValue, lhsCode == rhsCode {
return true
} else {
return false
}
}
}
static func <(lhs: TranslationSettingsControllerEntry, rhs: TranslationSettingsControllerEntry) -> Bool {
return lhs.stableId < rhs.stableId
}
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
let arguments = arguments as! TranslationSettingsControllerArguments
switch self {
case let .language(_, _, title, subtitle, value, code):
return LocalizationListItem(presentationData: presentationData, id: code, title: title, subtitle: subtitle, checked: value, activity: false, loading: false, editing: LocalizationListItemEditing(editable: false, editing: false, revealed: false, reorderable: false), sectionId: self.section, alwaysPlain: false, action: {
arguments.updateLanguageSelected(code, !value)
}, setItemWithRevealedOptions: { _, _ in }, removeItem: { _ in })
}
}
}
private func translationSettingsControllerEntries(theme: PresentationTheme, strings: PresentationStrings, initiallySelectedLanguages: Set<String>, settings: TranslationSettings, languages: [(String, String, String)]) -> [TranslationSettingsControllerEntry] {
var entries: [TranslationSettingsControllerEntry] = []
var index: Int32 = 0
var selectedLanguages: Set<String>
if let ignoredLanguages = settings.ignoredLanguages {
selectedLanguages = Set(ignoredLanguages)
} else {
selectedLanguages = Set([strings.baseLanguageCode])
for language in systemLanguageCodes() {
selectedLanguages.insert(language)
}
}
var addedLanguages = Set<String>()
for (code, title, subtitle) in languages {
if !addedLanguages.contains(code), initiallySelectedLanguages.contains(code) {
addedLanguages.insert(code)
entries.append(.language(index, theme, title, subtitle, selectedLanguages.contains(code), code))
index += 1
}
}
for (code, title, subtitle) in languages {
if !addedLanguages.contains(code) {
addedLanguages.insert(code)
entries.append(.language(index, theme, title, subtitle, selectedLanguages.contains(code), code))
index += 1
}
}
return entries
}
public func translationSettingsController(context: AccountContext) -> ViewController {
let actionsDisposable = DisposableSet()
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let interfaceLanguageCode = presentationData.strings.baseLanguageCode
let arguments = TranslationSettingsControllerArguments(context: context, updateLanguageSelected: { code, value in
let _ = updateTranslationSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in
var updated = current
var updatedIgnoredLanguages = updated.ignoredLanguages ?? []
if current.ignoredLanguages == nil {
updatedIgnoredLanguages.append(interfaceLanguageCode)
for language in systemLanguageCodes() {
if !updatedIgnoredLanguages.contains(language) {
updatedIgnoredLanguages.append(language)
}
}
}
if value {
if !updatedIgnoredLanguages.contains(code) {
updatedIgnoredLanguages.append(code)
}
} else {
updatedIgnoredLanguages.removeAll(where: { $0 == code })
}
updated = updated.withUpdatedIgnoredLanguages(updatedIgnoredLanguages)
return updated
}).start()
})
let enLocale = Locale(identifier: "en")
var languages: [(String, String, String)] = []
var addedLanguages = Set<String>()
for code in popularTranslationLanguages {
if let title = enLocale.localizedString(forLanguageCode: code) {
let languageLocale = Locale(identifier: code)
let subtitle = languageLocale.localizedString(forLanguageCode: code) ?? title
let value = (code, title.capitalized, subtitle.capitalized)
if code == interfaceLanguageCode {
languages.insert(value, at: 0)
} else {
languages.append(value)
}
addedLanguages.insert(code)
}
}
for code in supportedTranslationLanguages {
if !addedLanguages.contains(code), let title = enLocale.localizedString(forLanguageCode: code) {
let languageLocale = Locale(identifier: code)
let subtitle = languageLocale.localizedString(forLanguageCode: code) ?? title
let value = (code, title.capitalized, subtitle.capitalized)
if code == interfaceLanguageCode {
languages.insert(value, at: 0)
} else {
languages.append(value)
}
}
}
let initiallySelectedLanguages = Atomic<Set<String>?>(value: nil)
let sharedData = context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.translationSettings])
let signal = combineLatest(queue: Queue.mainQueue(), context.sharedContext.presentationData, sharedData)
|> map { presentationData, sharedData -> (ItemListControllerState, (ItemListNodeState, Any)) in
let settings = sharedData.entries[ApplicationSpecificSharedDataKeys.translationSettings]?.get(TranslationSettings.self) ?? TranslationSettings.defaultSettings
let initiallySelectedLanguages = initiallySelectedLanguages.modify({ current in
if let current {
return current
} else {
var selectedLanguages: Set<String>
if let ignoredLanguages = settings.ignoredLanguages {
selectedLanguages = Set(ignoredLanguages)
} else {
selectedLanguages = Set([presentationData.strings.baseLanguageCode])
for language in systemLanguageCodes() {
selectedLanguages.insert(language)
}
}
return selectedLanguages
}
})
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.DoNotTranslate_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: translationSettingsControllerEntries(theme: presentationData.theme, strings: presentationData.strings, initiallySelectedLanguages: initiallySelectedLanguages ?? Set(), settings: settings, languages: languages), style: .blocks, animateChanges: false)
return (controllerState, (listState, arguments))
}
|> afterDisposed {
actionsDisposable.dispose()
}
let controller = ItemListController(context: context, state: signal)
controller.alwaysSynchronous = true
return controller
}